## Automatically generated incremental diff
## From:   linux-2.5.66-bk8
## To:     linux-2.5.66-bk9
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.5.66-bk8/Documentation/i2c/proc-interface linux-2.5.66-bk9/Documentation/i2c/proc-interface
--- linux-2.5.66-bk8/Documentation/i2c/proc-interface	2003-03-24 14:01:14.000000000 -0800
+++ linux-2.5.66-bk9/Documentation/i2c/proc-interface	1969-12-31 16:00:00.000000000 -0800
@@ -1,53 +0,0 @@
-i2c-core is the core i2c module (surprise!) which offers general routines on
-which other modules build. You will find that all i2c-related modules depend
-on this module, so it will (need to) be loaded whenever another i2c-related 
-module is loaded. Seen from the outside, the most interesting is the /proc 
-interface. Note that there is no corresponding sysctl interface!
-
-/proc/bus/i2c
-=============
-
-Whenever i2c-core is loaded, you will find a file /proc/bus/i2c, which lists
-all currently registered I2C adapters. Each line contains exactly one
-I2C adapter. Each line has the following format: "i2c-%d\t%9s\t%-32s't%-32s\n",
-which works out to four columns separated by tabs. Note that the file
-will be empty, if no adapters are registered at all.
-
-Adapters are numbered from 0 upwards. The first column contains the number
-of the adapter, for example "i2c-4" for adapter 4. The name listed is also
-the name of the /proc file which lists all devices attached to it, and
-of the /dev file which corresponds to this adapter.
-
-The second column documents what kind of adapter this is. Some adapters
-understand the full I2C protocol, others only a subset called SMBus,
-and yet others are some kind of pseudo-adapters that do not understand
-i2c at all. Possible values in here are "i2c", "smbus", "i2c/smbus"
-and "dummy". Because the SMBus protocol can be fully emulated by i2c
-adapters, if you see "i2c" here, SMBus is supported too. There may
-be some future adapters which support both specific SMBus commands and
-general I2C, and they will display "i2c/smbus".
-
-The third and fourth column are respectively the algorithm and adapter
-name of this adapter. Each adapter is associated with an algorithm,
-and several adapters can share the same algorithm. The combination of
-algorithm name and adapter name should be unique for an adapter, but
-you can't really count on that yet.
-
-
-/proc/bus/i2c-*
-===============
-
-Each registered adapter gets its own file in /proc/bus/, which lists
-the devices registered to the adapter. Each line in such a file contains
-one registered device. Each line has the following format:
-"%02x\t%-32s\t%-32s\n", which works out to three columns separated by
-tabs. Note that this file can be empty, if no devices are found on 
-the adapter.
-
-The first column contains the (hexadecimal) address of the client. As 
-only 7-bit addresses are supported at this moment, two digits are
-enough. 
-
-The second and third column are respectively the client name and the
-driver name of this client. Each client is associated with a driver,
-and several clients can share the same driver.
diff -urN linux-2.5.66-bk8/Documentation/i2c/sysfs-interface linux-2.5.66-bk9/Documentation/i2c/sysfs-interface
--- linux-2.5.66-bk8/Documentation/i2c/sysfs-interface	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/Documentation/i2c/sysfs-interface	2003-04-03 04:32:41.000000000 -0800
@@ -0,0 +1,177 @@
+Naming and data format standards for sysfs files
+------------------------------------------------
+
+The libsensors library offers an interface to the raw sensors data
+through the sysfs interface. See libsensors documentation and source for
+more further information.
+
+An alternative method that some programs use is to access the sysfs
+files directly. This document briefly describes the standards that the
+drivers follow, so that an application program can scan for entries and
+access this data in a simple and consistent way.
+
+If you are developing a userspace application please send us feedback on
+this standard.
+
+Note that motherboards vary widely in the connections to sensor chips.
+There is no standard that ensures, for example, that the second
+temperature sensor is connected to the CPU, or that the second fan is on
+the CPU. Therefore, programs must provide a facility for the user to
+label or bind /proc entries for display.  Sensor chips often have unused
+inputs that should be ignored by user programs.
+
+Each chip gets its own directory in the sysfs /sys/devices tree.  To
+find all sensor chips, it is easier to follow the symlinks from
+/sys/i2c/devices/
+
+All sysfs values are fixed point numbers.  To get the true value of some
+of the values, you should divide by the specified value.
+
+There is only one value per file, unlike the older /proc specification.
+
+Alarms are direct indications read from the chips. The drivers do NOT
+make comparisons of readings to thresholds. This allows violations
+between readings to be caught and alarmed. The exact definition of an
+alarm (for example, whether a threshold must be met or must be exceeded
+to cause an alarm) is chip-dependent.
+
+
+-------------------------------------------------------------------------
+
+sysfs entries are as follows:
+
+
+Entry		Function
+-----		--------
+alarms		Alarm bitmask.
+		Read only.
+		Integer representation of one to four bytes.
+		A '1' bit means an alarm.
+		Chips should be programmed for 'comparator' mode so that
+		the alarm will 'come back' after you read the register
+		if it is still valid.
+		Generally a direct representation of a chip's internal
+		alarm registers; there is no standard for the position
+		of individual bits.
+		Bits are defined in kernel/include/sensors.h.
+
+beep_enable	Beep/interrupt enable
+		0 to disable.
+		1 to enable.
+		Read/Write
+
+beep_mask	Bitmask for beep.
+		Same format as 'alarms' with the same bit locations.
+		Read only.
+
+curr_max[1-n]	Current max value
+		Fixed point XXXXX, divide by 1000 to get Amps.
+		Read/Write.
+
+curr_min[1-n]	Current min or hysteresis value.
+		Preferably a hysteresis value, reported as a absolute
+		current, NOT a delta from the max value.
+		Fixed point XXXXX, divide by 1000 to get Amps.
+		Read/Write.
+
+curr_input[1-n]	Current input value
+		Fixed point XXXXX, divide by 1000 to get Amps.
+		Read only.
+		
+fan_min[1-3]	Fan minimum value
+		Integer value indicating RPM
+		Read/Write.
+
+fan_input[1-3]	Fan input value.
+		Integer value indicating RPM
+		Read only.
+
+fan_div[1-3]	Fan divisor.
+		Integers in powers of two (1,2,4,8,16,32,64,128).
+		Some chips only support values 1,2,4,8.
+		See doc/fan-divisors for details.
+
+in_min[0-8]	Voltage min value.
+		Fixed point value in form XXXX.  Divide by 1000 to get
+		Volts.
+		Read/Write
+		
+in_max[0-8]	Voltage max value.
+		Fixed point value in form XXXX.  Divide by 1000 to get
+		Volts.
+		Read/Write
+		
+in_input[0-8]	Voltage input value.
+		Fixed point value in form XXXX.  Divide by 1000 to get
+		Volts.
+		Read only
+		Actual voltage depends on the scaling resistors on the
+		motherboard, as recommended in the chip datasheet.
+		This varies by chip and by motherboard.
+		Because of this variation, values are generally NOT scaled
+		by the chip driver, and must be done by the application.
+		However, some drivers (notably lm87 and via686a)
+		do scale, with various degrees of success.
+		These drivers will output the actual voltage.
+		First two values are read/write and third is read only.
+		Typical usage:
+			in_*0	CPU #1 voltage (not scaled)
+			in_*1	CPU #1 voltage (not scaled)
+			in_*2	3.3V nominal (not scaled)
+			in_*3	5.0V nominal (scaled)
+			in_*4	12.0V nominal (scaled)
+			in_*5	-12.0V nominal (scaled)
+			in_*6	-5.0V nominal (scaled)
+			in_*7	varies
+			in_*8	varies
+
+pwm[1-3]	Pulse width modulation fan control.
+		Integer 0 - 255
+		Read/Write
+		255 is max or 100%.
+		Corresponds to the fans 1-3.
+
+pwm_enable[1-3] pwm enable
+		not always present even if pwm* is.
+		0 to turn off
+		1 to turn on
+		Read/Write
+
+sensor[1-3]	Sensor type selection.
+		Integers 1,2,3, or thermistor Beta value (3435)
+		Read/Write.
+
+temp_max[1-3]	Temperature max value.
+		Fixed point value in form XXXXX and should be divided by
+		1000 to get degrees Celsius.
+		Read/Write value.
+
+temp_min[1-3]	Temperature min or hysteresis value.
+		Fixed point value in form XXXXX and should be divided by
+		1000 to get degrees Celsius.  This is preferably a
+		hysteresis value, reported as a absolute temperature,
+		NOT a delta from the max value.
+		Read/Write value.
+
+temp_input[1-3] Temperature input value.
+		Read only value.
+
+		If there are multiple temperature sensors, temp_*1 is
+		generally the sensor inside the chip itself, generally
+		reported as "motherboard temperature".  temp_*2 and
+		temp_*3 are generally sensors external to the chip
+		itself, for example the thermal diode inside the CPU or
+		a thermistor nearby.
+
+vid		CPU core voltage.
+		Read only.
+		Fixed point value in form XXXX corresponding to CPU core
+		voltage as told to the sensor chip.  Divide by 1000 to
+		get Volts.  Not always correct.
+
+vrm		Voltage Regulator Module version number. 
+		Read only.
+		Two digit number (XX), first is major version, second is
+		minor version.
+		Affects the way the driver calculates the core voltage from
+		the vid pins. See doc/vid for details.
diff -urN linux-2.5.66-bk8/Makefile linux-2.5.66-bk9/Makefile
--- linux-2.5.66-bk8/Makefile	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/Makefile	2003-04-03 04:32:41.000000000 -0800
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 66
-EXTRAVERSION = -bk8
+EXTRAVERSION = -bk9
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
diff -urN linux-2.5.66-bk8/arch/i386/kernel/apic.c linux-2.5.66-bk9/arch/i386/kernel/apic.c
--- linux-2.5.66-bk8/arch/i386/kernel/apic.c	2003-03-24 14:01:50.000000000 -0800
+++ linux-2.5.66-bk9/arch/i386/kernel/apic.c	2003-04-03 04:32:41.000000000 -0800
@@ -10,6 +10,8 @@
  *					for testing these extensively.
  *	Maciej W. Rozycki	:	Various updates and fixes.
  *	Mikael Pettersson	:	Power Management for UP-APIC.
+ *	Pavel Machek and
+ *	Mikael Pettersson	:	PM converted to driver model.
  */
 
 #include <linux/config.h>
@@ -451,17 +453,14 @@
 
 #ifdef CONFIG_PM
 
-#include <linux/slab.h>
-#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/module.h>
 
 static struct {
 	/* 'active' is true if the local APIC was enabled by us and
 	   not the BIOS; this signifies that we are also responsible
 	   for disabling it before entering apm/acpi suspend */
 	int active;
-	/* 'perfctr_pmdev' is here because the current (2.4.1) PM
-	   callback system doesn't handle hierarchical dependencies */
-	struct pm_dev *perfctr_pmdev;
 	/* r/w apic fields */
 	unsigned int apic_id;
 	unsigned int apic_taskpri;
@@ -478,13 +477,16 @@
 	unsigned int apic_thmr;
 } apic_pm_state;
 
-static void apic_pm_suspend(void *data)
+static int lapic_suspend(struct device *dev, u32 state, u32 level)
 {
 	unsigned int l, h;
 	unsigned long flags;
 
-	if (apic_pm_state.perfctr_pmdev)
-		pm_send(apic_pm_state.perfctr_pmdev, PM_SUSPEND, data);
+	if (level != SUSPEND_POWER_DOWN)
+		return 0;
+	if (!apic_pm_state.active)
+		return 0;
+
 	apic_pm_state.apic_id = apic_read(APIC_ID);
 	apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
 	apic_pm_state.apic_ldr = apic_read(APIC_LDR);
@@ -505,13 +507,22 @@
 	l &= ~MSR_IA32_APICBASE_ENABLE;
 	wrmsr(MSR_IA32_APICBASE, l, h);
 	local_irq_restore(flags);
+	return 0;
 }
 
-static void apic_pm_resume(void *data)
+static int lapic_resume(struct device *dev, u32 level)
 {
 	unsigned int l, h;
 	unsigned long flags;
 
+	if (level != RESUME_POWER_ON)
+		return 0;
+	if (!apic_pm_state.active)
+		return 0;
+
+	/* XXX: Pavel needs this for S3 resume, but can't explain why */
+	set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
+
 	local_irq_save(flags);
 	rdmsr(MSR_IA32_APICBASE, l, h);
 	l &= ~MSR_IA32_APICBASE_BASE;
@@ -536,73 +547,45 @@
 	apic_write(APIC_ESR, 0);
 	apic_read(APIC_ESR);
 	local_irq_restore(flags);
-	if (apic_pm_state.perfctr_pmdev)
-		pm_send(apic_pm_state.perfctr_pmdev, PM_RESUME, data);
-}
-
-static int apic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-	switch (rqst) {
-	case PM_SUSPEND:
-		apic_pm_suspend(data);
-		break;
-	case PM_RESUME:
-		apic_pm_resume(data);
-		break;
-	}
 	return 0;
 }
 
-/* perfctr driver should call this instead of pm_register() */
-struct pm_dev *apic_pm_register(pm_dev_t type,
-				unsigned long id,
-				pm_callback callback)
-{
-	struct pm_dev *dev;
-
-	if (!apic_pm_state.active)
-		return pm_register(type, id, callback);
-	if (apic_pm_state.perfctr_pmdev)
-		return NULL;	/* we're busy */
-	dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
-	if (dev) {
-		memset(dev, 0, sizeof(*dev));
-		dev->type = type;
-		dev->id = id;
-		dev->callback = callback;
-		apic_pm_state.perfctr_pmdev = dev;
-	}
-	return dev;
-}
-
-/* perfctr driver should call this instead of pm_unregister() */
-void apic_pm_unregister(struct pm_dev *dev)
-{
-	if (!apic_pm_state.active) {
-		pm_unregister(dev);
-	} else if (dev == apic_pm_state.perfctr_pmdev) {
-		apic_pm_state.perfctr_pmdev = NULL;
-		kfree(dev);
-	}
-}
+static struct device_driver lapic_driver = {
+	.name		= "lapic",
+	.bus		= &system_bus_type,
+	.resume		= lapic_resume,
+	.suspend	= lapic_suspend,
+};
+
+/* not static, needed by child devices */
+struct sys_device device_lapic = {
+	.name		= "lapic",
+	.id		= 0,
+	.dev		= {
+		.name	= "lapic",
+		.driver	= &lapic_driver,
+	},
+};
+EXPORT_SYMBOL(device_lapic);
 
-static void __init apic_pm_init1(void)
+static void __init apic_pm_activate(void)
 {
-	/* can't pm_register() at this early stage in the boot process
-	   (causes an immediate reboot), so just set the flag */
 	apic_pm_state.active = 1;
 }
 
-static void __init apic_pm_init2(void)
+static int __init init_lapic_devicefs(void)
 {
-	if (apic_pm_state.active)
-		pm_register(PM_SYS_DEV, 0, apic_pm_callback);
+	if (!cpu_has_apic)
+		return 0;
+	/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
+	driver_register(&lapic_driver);
+	return sys_device_register(&device_lapic);
 }
+device_initcall(init_lapic_devicefs);
 
 #else	/* CONFIG_PM */
 
-static inline void apic_pm_init1(void) { }
-static inline void apic_pm_init2(void) { }
+static inline void apic_pm_activate(void) { }
 
 #endif	/* CONFIG_PM */
 
@@ -670,7 +653,7 @@
 
 	printk("Found and enabled local APIC!\n");
 
-	apic_pm_init1();
+	apic_pm_activate();
 
 	return 0;
 
@@ -1155,8 +1138,6 @@
 
 	phys_cpu_present_map = 1 << boot_cpu_physical_apicid;
 
-	apic_pm_init2();
-
 	setup_local_APIC();
 
 	if (nmi_watchdog == NMI_LOCAL_APIC)
diff -urN linux-2.5.66-bk8/arch/i386/kernel/apm.c linux-2.5.66-bk9/arch/i386/kernel/apm.c
--- linux-2.5.66-bk8/arch/i386/kernel/apm.c	2003-03-24 13:59:55.000000000 -0800
+++ linux-2.5.66-bk9/arch/i386/kernel/apm.c	2003-04-03 04:32:41.000000000 -0800
@@ -218,6 +218,7 @@
 #include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/pm.h>
+#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -1237,6 +1238,9 @@
 		}
 		printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
 	}
+
+	device_suspend(3, SUSPEND_POWER_DOWN);
+
 	/* serialize with the timer interrupt */
 	write_seqlock_irq(&xtime_lock);
 
@@ -1257,6 +1261,7 @@
 	if (err != APM_SUCCESS)
 		apm_error("suspend", err);
 	err = (err == APM_SUCCESS) ? 0 : -EIO;
+	device_resume(RESUME_POWER_ON);
 	pm_send_all(PM_RESUME, (void *)0);
 	queue_event(APM_NORMAL_RESUME, NULL);
  out:
@@ -1370,6 +1375,7 @@
 				write_seqlock_irq(&xtime_lock);
 				set_time();
 				write_sequnlock_irq(&xtime_lock);
+				device_resume(RESUME_POWER_ON);
 				pm_send_all(PM_RESUME, (void *)0);
 				queue_event(event, NULL);
 			}
diff -urN linux-2.5.66-bk8/arch/i386/kernel/i386_ksyms.c linux-2.5.66-bk9/arch/i386/kernel/i386_ksyms.c
--- linux-2.5.66-bk8/arch/i386/kernel/i386_ksyms.c	2003-03-24 14:01:48.000000000 -0800
+++ linux-2.5.66-bk9/arch/i386/kernel/i386_ksyms.c	2003-04-03 04:32:41.000000000 -0800
@@ -163,10 +163,6 @@
 EXPORT_SYMBOL(flush_tlb_page);
 #endif
 
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PM)
-EXPORT_SYMBOL_GPL(set_nmi_pm_callback);
-EXPORT_SYMBOL_GPL(unset_nmi_pm_callback);
-#endif
 #ifdef CONFIG_X86_IO_APIC
 EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 #endif
diff -urN linux-2.5.66-bk8/arch/i386/kernel/nmi.c linux-2.5.66-bk9/arch/i386/kernel/nmi.c
--- linux-2.5.66-bk8/arch/i386/kernel/nmi.c	2003-03-24 14:00:44.000000000 -0800
+++ linux-2.5.66-bk9/arch/i386/kernel/nmi.c	2003-04-03 04:32:41.000000000 -0800
@@ -9,6 +9,8 @@
  *  Mikael Pettersson	: AMD K7 support for local APIC NMI watchdog.
  *  Mikael Pettersson	: Power Management for local APIC NMI watchdog.
  *  Mikael Pettersson	: Pentium 4 support for local APIC NMI watchdog.
+ *  Pavel Machek and
+ *  Mikael Pettersson	: PM converted to driver model. Disable/enable API.
  */
 
 #include <linux/config.h>
@@ -20,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
+#include <linux/module.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
@@ -134,14 +137,18 @@
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-#ifdef CONFIG_PM
-
-#include <linux/pm.h>
-
-struct pm_dev *nmi_pmdev;
+/* nmi_active:
+ * +1: the lapic NMI watchdog is active, but can be disabled
+ *  0: the lapic NMI watchdog has not been set up, and cannot
+ *     be enabled
+ * -1: the lapic NMI watchdog is disabled, but can be enabled
+ */
+static int nmi_active;
 
-static void disable_apic_nmi_watchdog(void)
+void disable_lapic_nmi_watchdog(void)
 {
+	if (nmi_active <= 0)
+		return;
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
 		wrmsr(MSR_K7_EVNTSEL0, 0, 0);
@@ -158,46 +165,65 @@
 		}
 		break;
 	}
+	nmi_active = -1;
+	/* tell do_nmi() and others that we're not active any more */
+	nmi_watchdog = 0;
 }
 
-static int nmi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+void enable_lapic_nmi_watchdog(void)
 {
-	switch (rqst) {
-	case PM_SUSPEND:
-		disable_apic_nmi_watchdog();
-		break;
-	case PM_RESUME:
+	if (nmi_active < 0) {
+		nmi_watchdog = NMI_LOCAL_APIC;
 		setup_apic_nmi_watchdog();
-		break;
 	}
-	return 0;
 }
 
-struct pm_dev * set_nmi_pm_callback(pm_callback callback)
-{
-	apic_pm_unregister(nmi_pmdev);
-	return apic_pm_register(PM_SYS_DEV, 0, callback);
-}
+#ifdef CONFIG_PM
+
+#include <linux/device.h>
 
-void unset_nmi_pm_callback(struct pm_dev * dev)
+static int lapic_nmi_suspend(struct device *dev, u32 state, u32 level)
 {
-	apic_pm_unregister(dev);
-	nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
+	if (level != SUSPEND_POWER_DOWN)
+		return 0;
+	disable_lapic_nmi_watchdog();
+	return 0;
 }
- 
-static void nmi_pm_init(void)
+
+static int lapic_nmi_resume(struct device *dev, u32 level)
 {
-	if (!nmi_pmdev)
-		nmi_pmdev = apic_pm_register(PM_SYS_DEV, 0, nmi_pm_callback);
+	if (level != RESUME_POWER_ON)
+		return 0;
+	enable_lapic_nmi_watchdog();
+	return 0;
 }
 
-#define __pminit	/*empty*/
-
-#else	/* CONFIG_PM */
+static struct device_driver lapic_nmi_driver = {
+	.name		= "lapic_nmi",
+	.bus		= &system_bus_type,
+	.resume		= lapic_nmi_resume,
+	.suspend	= lapic_nmi_suspend,
+};
+
+static struct sys_device device_lapic_nmi = {
+	.name		= "lapic_nmi",
+	.id		= 0,
+	.dev		= {
+		.name	= "lapic_nmi",
+		.driver	= &lapic_nmi_driver,
+		.parent = &device_lapic.dev,
+	},
+};
 
-static inline void nmi_pm_init(void) { }
-
-#define __pminit	__init
+static int __init init_lapic_nmi_devicefs(void)
+{
+	if (nmi_active == 0)
+		return 0;
+	driver_register(&lapic_nmi_driver);
+	return sys_device_register(&device_lapic_nmi);
+}
+/* must come after the local APIC's device_initcall() */
+late_initcall(init_lapic_nmi_devicefs);
 
 #endif	/* CONFIG_PM */
 
@@ -206,7 +232,7 @@
  * Original code written by Keith Owens.
  */
 
-static void __pminit clear_msr_range(unsigned int base, unsigned int n)
+static void clear_msr_range(unsigned int base, unsigned int n)
 {
 	unsigned int i;
 
@@ -214,7 +240,7 @@
 		wrmsr(base+i, 0, 0);
 }
 
-static void __pminit setup_k7_watchdog(void)
+static void setup_k7_watchdog(void)
 {
 	unsigned int evntsel;
 
@@ -236,7 +262,7 @@
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
 }
 
-static void __pminit setup_p6_watchdog(void)
+static void setup_p6_watchdog(void)
 {
 	unsigned int evntsel;
 
@@ -258,7 +284,7 @@
 	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
 }
 
-static int __pminit setup_p4_watchdog(void)
+static int setup_p4_watchdog(void)
 {
 	unsigned int misc_enable, dummy;
 
@@ -288,7 +314,7 @@
 	return 1;
 }
 
-void __pminit setup_apic_nmi_watchdog (void)
+void setup_apic_nmi_watchdog (void)
 {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
@@ -312,7 +338,7 @@
 	default:
 		return;
 	}
-	nmi_pm_init();
+	nmi_active = 1;
 }
 
 static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
@@ -400,3 +426,7 @@
 		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
 	}
 }
+
+EXPORT_SYMBOL(nmi_watchdog);
+EXPORT_SYMBOL(disable_lapic_nmi_watchdog);
+EXPORT_SYMBOL(enable_lapic_nmi_watchdog);
diff -urN linux-2.5.66-bk8/arch/i386/oprofile/nmi_int.c linux-2.5.66-bk9/arch/i386/oprofile/nmi_int.c
--- linux-2.5.66-bk8/arch/i386/oprofile/nmi_int.c	2003-03-24 14:01:43.000000000 -0800
+++ linux-2.5.66-bk9/arch/i386/oprofile/nmi_int.c	2003-04-03 04:32:41.000000000 -0800
@@ -11,6 +11,7 @@
 #include <linux/notifier.h>
 #include <linux/smp.h>
 #include <linux/oprofile.h>
+#include <linux/device.h>
 #include <asm/nmi.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
@@ -25,27 +26,59 @@
 static int nmi_start(void);
 static void nmi_stop(void);
 
-static struct pm_dev * oprofile_pmdev;
- 
-/* We're at risk of causing big trouble unless we
- * make sure to not cause any NMI interrupts when
- * suspended.
- */
-static int oprofile_pm_callback(struct pm_dev * dev,
-		pm_request_t rqst, void * data)
-{
-	switch (rqst) {
-		case PM_SUSPEND:
-			nmi_stop();
-			break;
-		case PM_RESUME:
-			nmi_start();
-			break;
-	}
+/* 0 == registered but off, 1 == registered and on */
+static int nmi_enabled = 0;
+
+#ifdef CONFIG_PM
+
+static int nmi_suspend(struct device *dev, u32 state, u32 level)
+{
+	if (level != SUSPEND_POWER_DOWN)
+		return 0;
+	if (nmi_enabled == 1)
+		nmi_stop();
 	return 0;
 }
- 
- 
+
+
+static int nmi_resume(struct device *dev, u32 level)
+{
+	if (level != RESUME_POWER_ON)
+		return 0;
+	if (nmi_enabled == 1)
+		nmi_start();
+	return 0;
+}
+
+
+static struct device_driver nmi_driver = {
+	.name		= "oprofile",
+	.bus		= &system_bus_type,
+	.resume		= nmi_resume,
+	.suspend	= nmi_suspend,
+};
+
+
+static struct device device_nmi = {
+	.name	= "oprofile",
+	.bus_id = "oprofile",
+	.driver	= &nmi_driver,
+	.parent = &device_lapic.dev,
+};
+
+
+static int __init init_nmi_driverfs(void)
+{
+	driver_register(&nmi_driver);
+	return device_register(&device_nmi);
+}
+
+
+late_initcall(init_nmi_driverfs);
+
+#endif /* CONFIG_PM */
+
+
 static int nmi_callback(struct pt_regs * regs, int cpu)
 {
 	return model->check_ctrs(cpu, &cpu_msrs[cpu], regs);
@@ -86,7 +119,7 @@
 	saved_lvtpc[cpu] = apic_read(APIC_LVTPC);
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
- 
+
 
 static int nmi_setup(void)
 {
@@ -95,9 +128,10 @@
 	 * without actually triggering any NMIs as this will
 	 * break the core code horrifically.
 	 */
+	disable_lapic_nmi_watchdog();
 	on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
 	set_nmi_callback(nmi_callback);
-	oprofile_pmdev = set_nmi_pm_callback(oprofile_pm_callback);
+	nmi_enabled = 1;
 	return 0;
 }
 
@@ -145,9 +179,10 @@
  
 static void nmi_shutdown(void)
 {
-	unset_nmi_pm_callback(oprofile_pmdev);
+	nmi_enabled = 0;
 	unset_nmi_callback();
 	on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
+	enable_lapic_nmi_watchdog();
 }
 
  
diff -urN linux-2.5.66-bk8/drivers/i2c/Kconfig linux-2.5.66-bk9/drivers/i2c/Kconfig
--- linux-2.5.66-bk8/drivers/i2c/Kconfig	2003-03-24 14:00:09.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/Kconfig	2003-04-03 04:32:42.000000000 -0800
@@ -196,17 +196,6 @@
 	  <file:Documentation/modules.txt>.
 	  The module will be called i2c-dev.
 
-config I2C_PROC
-	tristate "I2C /proc interface (required for hardware sensors)"
-	depends on I2C && SYSCTL
-	help
-	  This provides support for i2c device entries in the /proc filesystem.
-	  The entries will be found in /proc/sys/dev/sensors.
-
-	  This code is also available as a module. If you want to compile
-	  it as a module, say M here and read <file:Documentation/modules.txt>.
-	  The module will be called i2c-proc.
-
 	source drivers/i2c/busses/Kconfig
 	source drivers/i2c/chips/Kconfig
 
diff -urN linux-2.5.66-bk8/drivers/i2c/Makefile linux-2.5.66-bk9/drivers/i2c/Makefile
--- linux-2.5.66-bk8/drivers/i2c/Makefile	2003-03-24 13:59:54.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/Makefile	2003-04-03 04:32:42.000000000 -0800
@@ -14,5 +14,5 @@
 obj-$(CONFIG_ITE_I2C_ADAP)	+= i2c-adap-ite.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
-obj-$(CONFIG_I2C_PROC)		+= i2c-proc.o
+obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
 obj-y				+= busses/ chips/
diff -urN linux-2.5.66-bk8/drivers/i2c/busses/Kconfig linux-2.5.66-bk9/drivers/i2c/busses/Kconfig
--- linux-2.5.66-bk8/drivers/i2c/busses/Kconfig	2003-03-24 14:01:23.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/busses/Kconfig	2003-04-03 04:32:42.000000000 -0800
@@ -1,13 +1,12 @@
 #
 # Sensor device configuration
-# All depend on EXPERIMENTAL, I2C and I2C_PROC.
 #
 
 menu "I2C Hardware Sensors Mainboard support"
 
 config I2C_ALI15X3
 	tristate "  ALI 15x3"
-	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the
 	  Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -21,7 +20,7 @@
 
 config I2C_AMD756
 	tristate "  AMD 756/766"
-	depends on I2C && I2C_PROC
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the AMD
 	  756/766/768 mainboard I2C interfaces.
@@ -38,7 +37,7 @@
 
 config I2C_AMD8111
 	tristate "  AMD 8111"
-	depends on I2C && I2C_PROC
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the AMD
 	  8111 mainboard I2C interfaces.
@@ -55,7 +54,7 @@
 
 config I2C_I801
 	tristate "  Intel 801"
-	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  801 family of mainboard I2C interfaces.  Specifically, the following
@@ -78,7 +77,7 @@
 
 config I2C_ISA
 	tristate "  ISA Bus support"
-	depends on I2C && I2C_PROC && ISA && EXPERIMENTAL
+	depends on I2C && ISA && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for i2c
 	  interfaces that are on the ISA bus.
@@ -96,7 +95,7 @@
 
 config I2C_PIIX4
 	tristate "  Intel PIIX4"
-	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/Kconfig linux-2.5.66-bk9/drivers/i2c/chips/Kconfig
--- linux-2.5.66-bk8/drivers/i2c/chips/Kconfig	2003-03-24 14:00:45.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/Kconfig	2003-04-03 04:32:42.000000000 -0800
@@ -1,13 +1,13 @@
 #
 # Sensor device configuration
-# All depend on EXPERIMENTAL, I2C and I2C_PROC.
+# All depend on EXPERIMENTAL and I2C
 #
 
 menu "I2C Hardware Sensors Chip support"
 
 config SENSORS_ADM1021
 	tristate "  Analog Devices ADM1021 and compatibles"
-	depends on I2C && I2C_PROC
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes here you get support for Analog Devices ADM1021 
 	  and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -24,7 +24,7 @@
 
 config SENSORS_LM75
 	tristate "  National Semiconductors LM75 and compatibles"
-	depends on I2C && I2C_PROC
+	depends on I2C && EXPERIMENTAL
 	help
 	  If you say yes here you get support for National Semiconductor LM75
 	  sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon
@@ -36,5 +36,37 @@
 	  You will also need the latest user-space utilties: you can find them
 	  in the lm_sensors package, which you can download at 
 	  http://www.lm-sensors.nu
+	  
+config SENSORS_VIA686A
+	tristate "  VIA686A"
+	depends on I2C && EXPERIMENTAL
+	help
+	  support for via686a
+	  If you say yes here you get support for the integrated sensors in
+	  Via 686A/B South Bridges. This can also be built as a module
+	  which can be inserted and removed while the kernel is running.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at
+	  http://www.lm-sensors.nu
+
+config SENSORS_W83781D
+	tristate "  Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Winbond W8378x series
+	  of sensor chips: the W83781D, W83782D, W83783S and W83682HF,
+	  and the similar Asus AS99127F. This
+	  can also be built as a module which can be inserted and removed
+	  while the kernel is running.
+	  
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at
+	  http://www.lm-sensors.nu
+
+config I2C_SENSOR
+	tristate
+	depends on SENSORS_ADM1021 || SENSORS_LM75 || SENSORS_VIA686A || SENSORS_W83781D
+	default m
 
 endmenu
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/Makefile linux-2.5.66-bk9/drivers/i2c/chips/Makefile
--- linux-2.5.66-bk8/drivers/i2c/chips/Makefile	2003-03-24 13:59:53.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/Makefile	2003-04-03 04:32:42.000000000 -0800
@@ -4,3 +4,5 @@
 
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
+obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
+obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/adm1021.c linux-2.5.66-bk9/drivers/i2c/chips/adm1021.c
--- linux-2.5.66-bk8/drivers/i2c/chips/adm1021.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/adm1021.c	2003-04-03 04:32:42.000000000 -0800
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-proc.h>
+#include <linux/i2c-sensor.h>
 
 
 /* Registers */
@@ -53,34 +53,34 @@
 
 /* The adm1021 registers */
 /* Read-only */
-#define ADM1021_REG_TEMP 0x00
-#define ADM1021_REG_REMOTE_TEMP 0x01
-#define ADM1021_REG_STATUS 0x02
-#define ADM1021_REG_MAN_ID 0x0FE	/* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
-#define ADM1021_REG_DEV_ID 0x0FF	/* ADM1021 = 0x0X, ADM1023 = 0x3X */
-#define ADM1021_REG_DIE_CODE 0x0FF	/* MAX1617A */
+#define ADM1021_REG_TEMP		0x00
+#define ADM1021_REG_REMOTE_TEMP		0x01
+#define ADM1021_REG_STATUS		0x02
+#define ADM1021_REG_MAN_ID		0x0FE	/* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
+#define ADM1021_REG_DEV_ID		0x0FF	/* ADM1021 = 0x0X, ADM1023 = 0x3X */
+#define ADM1021_REG_DIE_CODE		0x0FF	/* MAX1617A */
 /* These use different addresses for reading/writing */
-#define ADM1021_REG_CONFIG_R 0x03
-#define ADM1021_REG_CONFIG_W 0x09
-#define ADM1021_REG_CONV_RATE_R 0x04
-#define ADM1021_REG_CONV_RATE_W 0x0A
+#define ADM1021_REG_CONFIG_R		0x03
+#define ADM1021_REG_CONFIG_W		0x09
+#define ADM1021_REG_CONV_RATE_R		0x04
+#define ADM1021_REG_CONV_RATE_W		0x0A
 /* These are for the ADM1023's additional precision on the remote temp sensor */
-#define ADM1021_REG_REM_TEMP_PREC 0x010
-#define ADM1021_REG_REM_OFFSET 0x011
-#define ADM1021_REG_REM_OFFSET_PREC 0x012
-#define ADM1021_REG_REM_TOS_PREC 0x013
-#define ADM1021_REG_REM_THYST_PREC 0x014
+#define ADM1021_REG_REM_TEMP_PREC	0x010
+#define ADM1021_REG_REM_OFFSET		0x011
+#define ADM1021_REG_REM_OFFSET_PREC	0x012
+#define ADM1021_REG_REM_TOS_PREC	0x013
+#define ADM1021_REG_REM_THYST_PREC	0x014
 /* limits */
-#define ADM1021_REG_TOS_R 0x05
-#define ADM1021_REG_TOS_W 0x0B
-#define ADM1021_REG_REMOTE_TOS_R 0x07
-#define ADM1021_REG_REMOTE_TOS_W 0x0D
-#define ADM1021_REG_THYST_R 0x06
-#define ADM1021_REG_THYST_W 0x0C
-#define ADM1021_REG_REMOTE_THYST_R 0x08
-#define ADM1021_REG_REMOTE_THYST_W 0x0E
+#define ADM1021_REG_TOS_R		0x05
+#define ADM1021_REG_TOS_W		0x0B
+#define ADM1021_REG_REMOTE_TOS_R	0x07
+#define ADM1021_REG_REMOTE_TOS_W	0x0D
+#define ADM1021_REG_THYST_R		0x06
+#define ADM1021_REG_THYST_W		0x0C
+#define ADM1021_REG_REMOTE_THYST_R	0x08
+#define ADM1021_REG_REMOTE_THYST_W	0x0E
 /* write-only */
-#define ADM1021_REG_ONESHOT 0x0F
+#define ADM1021_REG_ONESHOT		0x0F
 
 
 /* Conversions. Rounding and limit checking is only done on the TO_REG
@@ -88,8 +88,8 @@
    these macros are called: arguments may be evaluated more than once.
    Fixing this is just not worth it. */
 /* Conversions  note: 1021 uses normal integer signed-byte format*/
-#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
-#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
+#define TEMP_FROM_REG(val)	(val > 127 ? val-256 : val)
+#define TEMP_TO_REG(val)	(SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
 
 /* Initial values */
 
@@ -97,44 +97,43 @@
 they don't quite work like a thermostat the way the LM75 does.  I.e., 
 a lower temp than THYST actually triggers an alarm instead of 
 clearing it.  Weird, ey?   --Phil  */
-#define adm1021_INIT_TOS 60
-#define adm1021_INIT_THYST 20
-#define adm1021_INIT_REMOTE_TOS 60
-#define adm1021_INIT_REMOTE_THYST 20
+#define adm1021_INIT_TOS		60
+#define adm1021_INIT_THYST		20
+#define adm1021_INIT_REMOTE_TOS		60
+#define adm1021_INIT_REMOTE_THYST	20
 
 /* Each client has this additional data */
 struct adm1021_data {
-	int sysctl_id;
 	enum chips type;
 
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
-	u8 temp, temp_os, temp_hyst;	/* Register values */
-	u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
+	u8	temp_max;	/* Register values */
+	u8	temp_hyst;
+	u8	temp_input;
+	u8	remote_temp_max;
+	u8	remote_temp_hyst;
+	u8	remote_temp_input;
+	u8	alarms;
+	/* special values for ADM1021 only */
+	u8	die_code;
         /* Special values for ADM1023 only */
-	u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec, 
-	   remote_temp_offset, remote_temp_offset_prec;
+	u8	remote_temp_prec;
+	u8	remote_temp_os_prec;
+	u8	remote_temp_hyst_prec;
+	u8	remote_temp_offset;
+	u8	remote_temp_offset_prec;
 };
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter);
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
-			  unsigned short flags, int kind);
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind);
 static void adm1021_init_client(struct i2c_client *client);
 static int adm1021_detach_client(struct i2c_client *client);
 static int adm1021_read_value(struct i2c_client *client, u8 reg);
 static int adm1021_write_value(struct i2c_client *client, u8 reg,
 			       u16 value);
-static void adm1021_temp(struct i2c_client *client, int operation,
-			 int ctl_name, int *nrels_mag, long *results);
-static void adm1021_remote_temp(struct i2c_client *client, int operation,
-				int ctl_name, int *nrels_mag,
-				long *results);
-static void adm1021_alarms(struct i2c_client *client, int operation,
-			   int ctl_name, int *nrels_mag, long *results);
-static void adm1021_die_code(struct i2c_client *client, int operation,
-			     int ctl_name, int *nrels_mag, long *results);
 static void adm1021_update_client(struct i2c_client *client);
 
 /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
@@ -151,45 +150,63 @@
 	.detach_client	= adm1021_detach_client,
 };
 
-/* These files are created for each detected adm1021. This is just a template;
-   though at first sight, you might think we could use a statically
-   allocated list, we need some way to get back to the parent - which
-   is done through one of the 'extra' fields which are initialized
-   when a new copy is allocated. */
-static ctl_table adm1021_dir_table_template[] = {
-	{ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_temp},
-	{ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_remote_temp},
-	{ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_die_code},
-	{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_alarms},
-	{0}
-};
-
-static ctl_table adm1021_max_dir_table_template[] = {
-	{ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_temp},
-	{ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_remote_temp},
-	{ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &adm1021_alarms},
-	{0}
-};
-
 /* I choose here for semi-static allocation. Complete dynamic
    allocation could also be used; the code needed for this would probably
    take more memory than the datastructure takes now. */
 static int adm1021_id = 0;
 
+#define show(value)	\
+static ssize_t show_##value(struct device *dev, char *buf)	\
+{								\
+	struct i2c_client *client = to_i2c_client(dev);		\
+	struct adm1021_data *data = i2c_get_clientdata(client);	\
+	int temp;						\
+								\
+	adm1021_update_client(client);				\
+	temp = TEMP_FROM_REG(data->value);			\
+	return sprintf(buf, "%d\n", temp);			\
+}
+show(temp_max);
+show(temp_hyst);
+show(temp_input);
+show(remote_temp_max);
+show(remote_temp_hyst);
+show(remote_temp_input);
+show(alarms);
+show(die_code);
+
+#define set(value, reg)	\
+static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+{								\
+	struct i2c_client *client = to_i2c_client(dev);		\
+	struct adm1021_data *data = i2c_get_clientdata(client);	\
+	int temp = simple_strtoul(buf, NULL, 10);		\
+								\
+	data->value = TEMP_TO_REG(temp);			\
+	adm1021_write_value(client, reg, data->value);		\
+	return count;						\
+}
+set(temp_max, ADM1021_REG_TOS_W);
+set(temp_hyst, ADM1021_REG_THYST_W);
+set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W);
+set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W);
+
+static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static DEVICE_ATTR(temp_min1, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input, NULL);
+static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
+static DEVICE_ATTR(temp_min2, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
+static DEVICE_ATTR(temp_input2, S_IRUGO, show_remote_temp_input, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
+
+
 static int adm1021_attach_adapter(struct i2c_adapter *adapter)
 {
 	return i2c_detect(adapter, &addr_data, adm1021_detect);
 }
 
-static int adm1021_detect(struct i2c_adapter *adapter, int address,
-			  unsigned short flags, int kind)
+static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
 	struct i2c_client *new_client;
@@ -202,8 +219,7 @@
 	   at this moment; i2c_detect really won't call us. */
 #ifdef DEBUG
 	if (i2c_is_isa_adapter(adapter)) {
-		printk
-		    ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
+		dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
 		return 0;
 	}
 #endif
@@ -232,35 +248,28 @@
 	new_client->flags = 0;
 
 	/* Now, we do the remaining detection. */
-
 	if (kind < 0) {
-		if (
-		    (adm1021_read_value(new_client, ADM1021_REG_STATUS) &
-		     0x03) != 0x00)
+		if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00)
 			goto error1;
 	}
 
 	/* Determine the chip type. */
-
 	if (kind <= 0) {
 		i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
 		if (i == 0x41)
-		  if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
-			kind = adm1023;
-		  else
-			kind = adm1021;
+			if ((adm1021_read_value(new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
+				kind = adm1023;
+			else
+				kind = adm1021;
 		else if (i == 0x49)
 			kind = thmc10;
 		else if (i == 0x23)
 			kind = gl523sm;
 		else if ((i == 0x4d) &&
-			 (adm1021_read_value
-			  (new_client, ADM1021_REG_DEV_ID) == 0x01))
+			 (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) == 0x01))
 			kind = max1617a;
 		/* LM84 Mfr ID in a different place */
-		else
-		    if (adm1021_read_value
-			(new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
+		else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
 			kind = lm84;
 		else if (i == 0x54)
 			kind = mc1066;
@@ -293,10 +302,8 @@
 		type_name = "mc1066";
 		client_name = "MC1066 chip";
 	} else {
-#ifdef DEBUG
-		printk("adm1021.o: Internal error: unknown kind (%d)?!?",
-		       kind);
-#endif
+		dev_err(&adapter->dev, "Internal error: unknown kind (%d)?!?",
+			kind);
 		goto error1;
 	}
 
@@ -312,25 +319,24 @@
 	if ((err = i2c_attach_client(new_client)))
 		goto error3;
 
-	/* Register a new directory entry with module sensors */
-	err = i2c_register_entry(new_client, type_name,
-			(data->type == adm1021) ?
-				adm1021_dir_table_template :
-				adm1021_max_dir_table_template);
-	if (err < 0)
-		goto error4;
+	device_create_file(&new_client->dev, &dev_attr_temp_max1);
+	device_create_file(&new_client->dev, &dev_attr_temp_min1);
+	device_create_file(&new_client->dev, &dev_attr_temp_input1);
+	device_create_file(&new_client->dev, &dev_attr_temp_max2);
+	device_create_file(&new_client->dev, &dev_attr_temp_min2);
+	device_create_file(&new_client->dev, &dev_attr_temp_input2);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+	if (data->type == adm1021)
+		device_create_file(&new_client->dev, &dev_attr_die_code);
 
-	data->sysctl_id = err;
 	/* Initialize the ADM1021 chip */
 	adm1021_init_client(new_client);
 	return 0;
 
-      error4:
-	i2c_detach_client(new_client);
-      error3:
-      error1:
+error3:
+error1:
 	kfree(new_client);
-      error0:
+error0:
 	return err;
 }
 
@@ -353,21 +359,15 @@
 
 static int adm1021_detach_client(struct i2c_client *client)
 {
-
 	int err;
 
-	i2c_deregister_entry(((struct adm1021_data *) (i2c_get_clientdata(client)))->sysctl_id);
-
 	if ((err = i2c_detach_client(client))) {
-		printk
-		    ("adm1021.o: Client deregistration failed, client not detached.\n");
+		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
 		return err;
 	}
 
 	kfree(client);
-
 	return 0;
-
 }
 
 /* All registers are byte-sized */
@@ -391,39 +391,23 @@
 
 	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
 	    (jiffies < data->last_updated) || !data->valid) {
+		dev_dbg(&client->dev, "Starting adm1021 update\n");
 
-#ifdef DEBUG
-		printk("Starting adm1021 update\n");
-#endif
-
-		data->temp = adm1021_read_value(client, ADM1021_REG_TEMP);
-		data->temp_os =
-		    adm1021_read_value(client, ADM1021_REG_TOS_R);
-		data->temp_hyst =
-		    adm1021_read_value(client, ADM1021_REG_THYST_R);
-		data->remote_temp =
-		    adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
-		data->remote_temp_os =
-		    adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
-		data->remote_temp_hyst =
-		    adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
-		data->alarms =
-		    adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+		data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
+		data->temp_max = adm1021_read_value(client, ADM1021_REG_TOS_R);
+		data->temp_hyst = adm1021_read_value(client, ADM1021_REG_THYST_R);
+		data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
+		data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
+		data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
+		data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
 		if (data->type == adm1021)
-			data->die_code =
-			    adm1021_read_value(client,
-					       ADM1021_REG_DIE_CODE);
+			data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
 		if (data->type == adm1023) {
-		  data->remote_temp_prec =
-		    adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
-		  data->remote_temp_os_prec =
-		    adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
-		  data->remote_temp_hyst_prec =
-		    adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
-		  data->remote_temp_offset =
-		    adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
-		  data->remote_temp_offset_prec =
-		    adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
+			data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
+			data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
+			data->remote_temp_hyst_prec = adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
+			data->remote_temp_offset = adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
+			data->remote_temp_offset_prec = adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
 		}
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -433,6 +417,9 @@
 }
 
 
+/* FIXME, remove these four functions, they are here to verify the sysfs
+ * conversion is correct, or not */
+__attribute__((unused))
 static void adm1021_temp(struct i2c_client *client, int operation,
 			 int ctl_name, int *nrels_mag, long *results)
 {
@@ -442,15 +429,15 @@
 		*nrels_mag = 0;
 	else if (operation == SENSORS_PROC_REAL_READ) {
 		adm1021_update_client(client);
-		results[0] = TEMP_FROM_REG(data->temp_os);
+		results[0] = TEMP_FROM_REG(data->temp_max);
 		results[1] = TEMP_FROM_REG(data->temp_hyst);
-		results[2] = TEMP_FROM_REG(data->temp);
+		results[2] = TEMP_FROM_REG(data->temp_input);
 		*nrels_mag = 3;
 	} else if (operation == SENSORS_PROC_REAL_WRITE) {
 		if (*nrels_mag >= 1) {
-			data->temp_os = TEMP_TO_REG(results[0]);
+			data->temp_max = TEMP_TO_REG(results[0]);
 			adm1021_write_value(client, ADM1021_REG_TOS_W,
-					    data->temp_os);
+					    data->temp_max);
 		}
 		if (*nrels_mag >= 2) {
 			data->temp_hyst = TEMP_TO_REG(results[1]);
@@ -460,6 +447,7 @@
 	}
 }
 
+__attribute__((unused))
 static void adm1021_remote_temp(struct i2c_client *client, int operation,
 				int ctl_name, int *nrels_mag, long *results)
 {
@@ -471,68 +459,53 @@
                  else { *nrels_mag = 0; }
 	else if (operation == SENSORS_PROC_REAL_READ) {
 		adm1021_update_client(client);
-		results[0] = TEMP_FROM_REG(data->remote_temp_os);
+		results[0] = TEMP_FROM_REG(data->remote_temp_max);
 		results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
-		results[2] = TEMP_FROM_REG(data->remote_temp);
+		results[2] = TEMP_FROM_REG(data->remote_temp_input);
 		if (data->type == adm1023) {
-		  results[0]=results[0]*1000 + 
-		   ((data->remote_temp_os_prec >> 5) * 125);
-		  results[1]=results[1]*1000 + 
-		   ((data->remote_temp_hyst_prec >> 5) * 125);
-		  results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) + 
-                   ((data->remote_temp_offset_prec >> 5) * 125);
-		  results[3]=TEMP_FROM_REG(data->remote_temp)*1000 + 
-		   ((data->remote_temp_prec >> 5) * 125);
- 		  *nrels_mag = 4;
+			results[0] = results[0]*1000 + ((data->remote_temp_os_prec >> 5) * 125);
+			results[1] = results[1]*1000 + ((data->remote_temp_hyst_prec >> 5) * 125);
+			results[2] = (TEMP_FROM_REG(data->remote_temp_offset)*1000) + ((data->remote_temp_offset_prec >> 5) * 125);
+			results[3] = (TEMP_FROM_REG(data->remote_temp_input)*1000) + ((data->remote_temp_prec >> 5) * 125);
+			*nrels_mag = 4;
 		} else {
- 		  *nrels_mag = 3;
+ 			*nrels_mag = 3;
 		}
 	} else if (operation == SENSORS_PROC_REAL_WRITE) {
 		if (*nrels_mag >= 1) {
 			if (data->type == adm1023) {
-			  prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
-			  adm1021_write_value(client,
-                                            ADM1021_REG_REM_TOS_PREC,
-                                            prec);
-			  results[0]=results[0]/1000;
-			  data->remote_temp_os_prec=prec;
+				prec = ((results[0]-((results[0]/1000)*1000))/125)<<5;
+				adm1021_write_value(client, ADM1021_REG_REM_TOS_PREC, prec);
+				results[0] = results[0]/1000;
+				data->remote_temp_os_prec=prec;
 			}
-			data->remote_temp_os = TEMP_TO_REG(results[0]);
-			adm1021_write_value(client,
-					    ADM1021_REG_REMOTE_TOS_W,
-					    data->remote_temp_os);
+			data->remote_temp_max = TEMP_TO_REG(results[0]);
+			adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W, data->remote_temp_max);
 		}
 		if (*nrels_mag >= 2) {
 			if (data->type == adm1023) {
-			  prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
-			  adm1021_write_value(client,
-                                            ADM1021_REG_REM_THYST_PREC,
-                                            prec);
-			  results[1]=results[1]/1000;
-			  data->remote_temp_hyst_prec=prec;
+				prec = ((results[1]-((results[1]/1000)*1000))/125)<<5;
+				adm1021_write_value(client, ADM1021_REG_REM_THYST_PREC, prec);
+				results[1] = results[1]/1000;
+				data->remote_temp_hyst_prec=prec;
 			}
 			data->remote_temp_hyst = TEMP_TO_REG(results[1]);
-			adm1021_write_value(client,
-					    ADM1021_REG_REMOTE_THYST_W,
-					    data->remote_temp_hyst);
+			adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W, data->remote_temp_hyst);
 		}
 		if (*nrels_mag >= 3) {
 			if (data->type == adm1023) {
-			  prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
-			  adm1021_write_value(client,
-                                            ADM1021_REG_REM_OFFSET_PREC,
-                                            prec);
-			  results[2]=results[2]/1000;
-			  data->remote_temp_offset_prec=prec;
-			  data->remote_temp_offset=results[2];
-			  adm1021_write_value(client,
-                                            ADM1021_REG_REM_OFFSET,
-                                            data->remote_temp_offset);
+				prec = ((results[2]-((results[2]/1000)*1000))/125)<<5;
+				adm1021_write_value(client, ADM1021_REG_REM_OFFSET_PREC, prec);
+				results[2]=results[2]/1000;
+				data->remote_temp_offset_prec=prec;
+				data->remote_temp_offset=results[2];
+				adm1021_write_value(client, ADM1021_REG_REM_OFFSET, data->remote_temp_offset);
 			}
 		}
 	}
 }
 
+__attribute__((unused))
 static void adm1021_die_code(struct i2c_client *client, int operation,
 			     int ctl_name, int *nrels_mag, long *results)
 {
@@ -549,6 +522,7 @@
 	}
 }
 
+__attribute__((unused))
 static void adm1021_alarms(struct i2c_client *client, int operation,
 			   int ctl_name, int *nrels_mag, long *results)
 {
@@ -574,8 +548,8 @@
 	i2c_del_driver(&adm1021_driver);
 }
 
-MODULE_AUTHOR
-    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
+		"Philip Edelbrock <phil@netroedge.com>");
 MODULE_DESCRIPTION("adm1021 driver");
 MODULE_LICENSE("GPL");
 
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/lm75.c linux-2.5.66-bk9/drivers/i2c/chips/lm75.c
--- linux-2.5.66-bk8/drivers/i2c/chips/lm75.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/lm75.c	2003-04-03 04:32:42.000000000 -0800
@@ -18,14 +18,14 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+/* #define DEBUG 1 */
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-proc.h>
-
+#include <linux/i2c-sensor.h>
 
-#define LM75_SYSCTL_TEMP 1200	/* Degrees Celsius * 10 */
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { SENSORS_I2C_END };
@@ -39,97 +39,113 @@
 /* Many LM75 constants specified below */
 
 /* The LM75 registers */
-#define LM75_REG_TEMP 0x00
-#define LM75_REG_CONF 0x01
-#define LM75_REG_TEMP_HYST 0x02
-#define LM75_REG_TEMP_OS 0x03
+#define LM75_REG_TEMP		0x00
+#define LM75_REG_CONF		0x01
+#define LM75_REG_TEMP_HYST	0x02
+#define LM75_REG_TEMP_OS	0x03
 
 /* Conversions. Rounding and limit checking is only done on the TO_REG
    variants. Note that you should be a bit careful with which arguments
    these macros are called: arguments may be evaluated more than once.
    Fixing this is just not worth it. */
-#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
-#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
+#define TEMP_FROM_REG(val)	((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
+#define TEMP_TO_REG(val)	(SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
 
 /* Initial values */
-#define LM75_INIT_TEMP_OS 600
-#define LM75_INIT_TEMP_HYST 500
+#define LM75_INIT_TEMP_OS	600
+#define LM75_INIT_TEMP_HYST	500
 
 /* Each client has this additional data */
 struct lm75_data {
-	int sysctl_id;
-
-	struct semaphore update_lock;
-	char valid;		/* !=0 if following fields are valid */
-	unsigned long last_updated;	/* In jiffies */
-
-	u16 temp, temp_os, temp_hyst;	/* Register values */
+	struct semaphore	update_lock;
+	char			valid;		/* !=0 if following fields are valid */
+	unsigned long		last_updated;	/* In jiffies */
+	u16			temp_input;	/* Register values */
+	u16			temp_max;
+	u16			temp_hyst;
 };
 
 static int lm75_attach_adapter(struct i2c_adapter *adapter);
-static int lm75_detect(struct i2c_adapter *adapter, int address,
-		       unsigned short flags, int kind);
+static int lm75_detect(struct i2c_adapter *adapter, int address, int kind);
 static void lm75_init_client(struct i2c_client *client);
 static int lm75_detach_client(struct i2c_client *client);
-static u16 swap_bytes(u16 val);
 static int lm75_read_value(struct i2c_client *client, u8 reg);
 static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
-static void lm75_temp(struct i2c_client *client, int operation,
-		      int ctl_name, int *nrels_mag, long *results);
 static void lm75_update_client(struct i2c_client *client);
 
 
 /* This is the driver that will be inserted */
 static struct i2c_driver lm75_driver = {
 	.owner		= THIS_MODULE,
-	.name		= "LM75 sensor",
+	.name		= "lm75",
 	.id		= I2C_DRIVERID_LM75,
 	.flags		= I2C_DF_NOTIFY,
 	.attach_adapter	= lm75_attach_adapter,
 	.detach_client	= lm75_detach_client,
 };
 
-/* These files are created for each detected LM75. This is just a template;
-   though at first sight, you might think we could use a statically
-   allocated list, we need some way to get back to the parent - which
-   is done through one of the 'extra' fields which are initialized
-   when a new copy is allocated. */
-static ctl_table lm75_dir_table_template[] = {
-	{LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
-	 &i2c_sysctl_real, NULL, &lm75_temp},
-	{0}
-};
-
 static int lm75_id = 0;
 
+#define show(value)	\
+static ssize_t show_##value(struct device *dev, char *buf)	\
+{								\
+	struct i2c_client *client = to_i2c_client(dev);		\
+	struct lm75_data *data = i2c_get_clientdata(client);	\
+	int temp;						\
+								\
+	lm75_update_client(client);				\
+	temp = TEMP_FROM_REG(data->value);			\
+	return sprintf(buf, "%d\n", temp * 100);		\
+}
+show(temp_max);
+show(temp_hyst);
+show(temp_input);
+
+#define set(value, reg)	\
+static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+{								\
+	struct i2c_client *client = to_i2c_client(dev);		\
+	struct lm75_data *data = i2c_get_clientdata(client);	\
+	int temp = simple_strtoul(buf, NULL, 10) / 100;		\
+								\
+	data->value = TEMP_TO_REG(temp);			\
+	lm75_write_value(client, reg, data->value);		\
+	return count;						\
+}
+set(temp_max, LM75_REG_TEMP_OS);
+set(temp_hyst, LM75_REG_TEMP_HYST);
+
+static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static DEVICE_ATTR(temp_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL);
+
 static int lm75_attach_adapter(struct i2c_adapter *adapter)
 {
 	return i2c_detect(adapter, &addr_data, lm75_detect);
 }
 
 /* This function is called by i2c_detect */
-static int lm75_detect(struct i2c_adapter *adapter, int address,
-		       unsigned short flags, int kind)
+static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, cur, conf, hyst, os;
 	struct i2c_client *new_client;
 	struct lm75_data *data;
 	int err = 0;
-	const char *type_name, *client_name;
+	const char *name;
 
 	/* Make sure we aren't probing the ISA bus!! This is just a safety check
 	   at this moment; i2c_detect really won't call us. */
 #ifdef DEBUG
 	if (i2c_is_isa_adapter(adapter)) {
-		printk
-		    ("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
-		return 0;
+		dev_dbg(&adapter->dev,
+			"lm75_detect called for an ISA bus adapter?!?\n");
+		goto exit;
 	}
 #endif
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 				     I2C_FUNC_SMBUS_WORD_DATA))
-		    goto error0;
+		goto exit;
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
@@ -138,7 +154,7 @@
 				   sizeof(struct lm75_data),
 				   GFP_KERNEL))) {
 		err = -ENOMEM;
-		goto error0;
+		goto exit;
 	}
 	memset(new_client, 0x00, sizeof(struct i2c_client) +
 				 sizeof(struct lm75_data));
@@ -157,16 +173,10 @@
 		hyst = i2c_smbus_read_word_data(new_client, 2);
 		os = i2c_smbus_read_word_data(new_client, 3);
 		for (i = 0; i <= 0x1f; i++)
-			if (
-			    (i2c_smbus_read_byte_data
-			     (new_client, i * 8 + 1) != conf)
-			    ||
-			    (i2c_smbus_read_word_data
-			     (new_client, i * 8 + 2) != hyst)
-			    ||
-			    (i2c_smbus_read_word_data
-			     (new_client, i * 8 + 3) != os))
-				goto error1;
+			if ((i2c_smbus_read_byte_data(new_client, i * 8 + 1) != conf) ||
+			    (i2c_smbus_read_word_data(new_client, i * 8 + 2) != hyst) ||
+			    (i2c_smbus_read_word_data(new_client, i * 8 + 3) != os))
+				goto exit_free;
 	}
 
 	/* Determine the chip type - only one kind supported! */
@@ -174,15 +184,15 @@
 		kind = lm75;
 
 	if (kind == lm75) {
-		type_name = "lm75";
-		client_name = "LM75 chip";
+		name = "lm75";
 	} else {
-		pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind);
-		goto error1;
+		dev_dbg(&adapter->dev, "Internal error: unknown kind (%d)?!?",
+			kind);
+		goto exit_free;
 	}
 
 	/* Fill in the remaining client fields and put it into the global list */
-	strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
+	strncpy(new_client->dev.name, name, DEVICE_NAME_SIZE);
 
 	new_client->id = lm75_id++;
 	data->valid = 0;
@@ -190,36 +200,23 @@
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
-		goto error3;
+		goto exit_free;
 
-	/* Register a new directory entry with module sensors */
-	i = i2c_register_entry(new_client, type_name, lm75_dir_table_template);
-	if (i < 0) {
-		err = i;
-		goto error4;
-	}
-	data->sysctl_id = i;
+	device_create_file(&new_client->dev, &dev_attr_temp_max);
+	device_create_file(&new_client->dev, &dev_attr_temp_min);
+	device_create_file(&new_client->dev, &dev_attr_temp_input);
 
 	lm75_init_client(new_client);
 	return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
-      error4:
-	i2c_detach_client(new_client);
-      error3:
-      error1:
+exit_free:
 	kfree(new_client);
-      error0:
+exit:
 	return err;
 }
 
 static int lm75_detach_client(struct i2c_client *client)
 {
-	struct lm75_data *data = i2c_get_clientdata(client);
-
-	i2c_deregister_entry(data->sysctl_id);
 	i2c_detach_client(client);
 	kfree(client);
 	return 0;
@@ -271,12 +268,11 @@
 
 	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
 	    (jiffies < data->last_updated) || !data->valid) {
-		pr_debug("Starting lm75 update\n");
+		dev_dbg(&client->dev, "Starting lm75 update\n");
 
-		data->temp = lm75_read_value(client, LM75_REG_TEMP);
-		data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS);
-		data->temp_hyst =
-		    lm75_read_value(client, LM75_REG_TEMP_HYST);
+		data->temp_input = lm75_read_value(client, LM75_REG_TEMP);
+		data->temp_max = lm75_read_value(client, LM75_REG_TEMP_OS);
+		data->temp_hyst = lm75_read_value(client, LM75_REG_TEMP_HYST);
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -284,33 +280,6 @@
 	up(&data->update_lock);
 }
 
-
-static void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
-		      int *nrels_mag, long *results)
-{
-	struct lm75_data *data = i2c_get_clientdata(client);
-	if (operation == SENSORS_PROC_REAL_INFO)
-		*nrels_mag = 1;
-	else if (operation == SENSORS_PROC_REAL_READ) {
-		lm75_update_client(client);
-		results[0] = TEMP_FROM_REG(data->temp_os);
-		results[1] = TEMP_FROM_REG(data->temp_hyst);
-		results[2] = TEMP_FROM_REG(data->temp);
-		*nrels_mag = 3;
-	} else if (operation == SENSORS_PROC_REAL_WRITE) {
-		if (*nrels_mag >= 1) {
-			data->temp_os = TEMP_TO_REG(results[0]);
-			lm75_write_value(client, LM75_REG_TEMP_OS,
-					 data->temp_os);
-		}
-		if (*nrels_mag >= 2) {
-			data->temp_hyst = TEMP_TO_REG(results[1]);
-			lm75_write_value(client, LM75_REG_TEMP_HYST,
-					 data->temp_hyst);
-		}
-	}
-}
-
 static int __init sensors_lm75_init(void)
 {
 	return i2c_add_driver(&lm75_driver);
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/via686a.c linux-2.5.66-bk9/drivers/i2c/chips/via686a.c
--- linux-2.5.66-bk8/drivers/i2c/chips/via686a.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/via686a.c	2003-04-03 04:32:42.000000000 -0800
@@ -0,0 +1,930 @@
+/*
+    via686a.c - Part of lm_sensors, Linux kernel modules
+                for hardware monitoring
+                
+    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
+                        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+			Mark Studebaker <mdsxyz123@yahoo.com>,
+			and Bob Dougherty <bobd@stanford.edu>
+    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew 
+    <j.teh@iname.com> and Alex van Kaam <darkside@chello.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    Supports the Via VT82C686A, VT82C686B south bridges.
+    Reports all as a 686A.
+    See doc/chips/via686a for details.
+    Warning - only supports a single device.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+
+/* 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");
+MODULE_PARM_DESC(force_addr,
+		 "Initialize the base address of the sensors");
+
+/* Addresses to scan.
+   Note that we can't determine the ISA address until we have initialized
+   our module */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
+static unsigned int normal_isa[] = { 0x0000, SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(via686a);
+
+/*
+   The Via 686a southbridge has a LM78-like chip integrated on the same IC.
+   This driver is a customized copy of lm78.c
+*/
+
+/* Many VIA686A constants specified below */
+
+/* Length of ISA address segment */
+#define VIA686A_EXTENT 0x80
+#define VIA686A_BASE_REG 0x70
+#define VIA686A_ENABLE_REG 0x74
+
+/* The VIA686A registers */
+/* ins numbered 0-4 */
+#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
+#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
+#define VIA686A_REG_IN(nr)     (0x22 + (nr))
+
+/* fans numbered 1-2 */
+#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
+#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
+
+/* the following values are as speced by VIA: */
+static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
+static const u8 regover[] = { 0x39, 0x3d, 0x1d };
+static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
+
+/* temps numbered 1-3 */
+#define VIA686A_REG_TEMP(nr)		(regtemp[(nr) - 1])
+#define VIA686A_REG_TEMP_OVER(nr)	(regover[(nr) - 1])
+#define VIA686A_REG_TEMP_HYST(nr)	(reghyst[(nr) - 1])
+#define VIA686A_REG_TEMP_LOW1	0x4b	// bits 7-6
+#define VIA686A_REG_TEMP_LOW23	0x49	// 2 = bits 5-4, 3 = bits 7-6
+
+#define VIA686A_REG_ALARM1 0x41
+#define VIA686A_REG_ALARM2 0x42
+#define VIA686A_REG_FANDIV 0x47
+#define VIA686A_REG_CONFIG 0x40
+/* The following register sets temp interrupt mode (bits 1-0 for temp1, 
+ 3-2 for temp2, 5-4 for temp3).  Modes are:
+    00 interrupt stays as long as value is out-of-range
+    01 interrupt is cleared once register is read (default)
+    10 comparator mode- like 00, but ignores hysteresis
+    11 same as 00 */
+#define VIA686A_REG_TEMP_MODE 0x4b
+/* We'll just assume that you want to set all 3 simultaneously: */
+#define VIA686A_TEMP_MODE_MASK 0x3F
+#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+   variants. 
+
+********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
+ From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
+ voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp
+ voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V
+ voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V
+ voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V
+ voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V
+ in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
+ That is:
+ volts = (25*regVal+133)*factor
+ regVal = (volts/factor-133)/25
+ (These conversions were contributed by Jonathan Teh Soon Yew 
+ <j.teh@iname.com>)
+ 
+ These get us close, but they don't completely agree with what my BIOS 
+ says- they are all a bit low.  But, it all we have to go on... */
+static inline u8 IN_TO_REG(long val, int inNum)
+{
+	/* to avoid floating point, we multiply everything by 100.
+	 val is guaranteed to be positive, so we can achieve the effect of 
+	 rounding by (...*10+5)/10.  Note that the *10 is hidden in the 
+	 /250 (which should really be /2500).
+	 At the end, we need to /100 because we *100 everything and we need
+	 to /10 because of the rounding thing, so we /1000.   */
+	if (inNum <= 1)
+		return (u8)
+		    SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000, 
+				  0, 255);
+	else if (inNum == 2)
+		return (u8)
+		    SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000, 
+				  0, 255);
+	else if (inNum == 3)
+		return (u8)
+		    SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000, 
+				  0, 255);
+	else
+		return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5)
+					  / 1000, 0, 255);
+}
+
+static inline long IN_FROM_REG(u8 val, int inNum)
+{
+	/* to avoid floating point, we multiply everything by 100.
+	 val is guaranteed to be positive, so we can achieve the effect of
+	 rounding by adding 0.5.  Or, to avoid fp math, we do (...*10+5)/10.
+	 We need to scale with *100 anyway, so no need to /100 at the end. */
+	if (inNum <= 1)
+		return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10);
+	else if (inNum == 2)
+		return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10);
+	else if (inNum == 3)
+		return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10);
+	else
+		return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10);
+}
+
+/********* FAN RPM CONVERSIONS ********/
+/* Higher register values = slower fans (the fan's strobe gates a counter).
+ But this chip saturates back at 0, not at 255 like all the other chips.
+ So, 0 means 0 RPM */
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+	if (rpm == 0)
+		return 0;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
+}
+
+#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
+
+/******** TEMP CONVERSIONS (Bob Dougherty) *********/
+/* linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
+      if(temp<169)
+              return double(temp)*0.427-32.08;
+      else if(temp>=169 && temp<=202)
+              return double(temp)*0.582-58.16;
+      else
+              return double(temp)*0.924-127.33;
+
+ A fifth-order polynomial fits the unofficial data (provided by Alex van 
+ Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable 
+ numbers on my machine (ie. they agree with what my BIOS tells me).  
+ Here's the fifth-order fit to the 8-bit data:
+ temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 - 
+        2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
+
+ (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for 
+ finding my typos in this formula!)
+
+ Alas, none of the elegant function-fit solutions will work because we 
+ aren't allowed to use floating point in the kernel and doing it with 
+ integers doesn't rpovide enough precision.  So we'll do boring old 
+ look-up table stuff.  The unofficial data (see below) have effectively 
+ 7-bit resolution (they are rounded to the nearest degree).  I'm assuming 
+ that the transfer function of the device is monotonic and smooth, so a 
+ smooth function fit to the data will allow us to get better precision.  
+ I used the 5th-order poly fit described above and solved for
+ VIA register values 0-255.  I *10 before rounding, so we get tenth-degree 
+ precision.  (I could have done all 1024 values for our 10-bit readings, 
+ but the function is very linear in the useful range (0-80 deg C), so 
+ we'll just use linear interpolation for 10-bit readings.)  So, tempLUT 
+ is the temp at via register values 0-255: */
+static const long tempLUT[] =
+    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+	    -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
+	    -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
+	    -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
+	    -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
+	    -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
+	    -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
+	    20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
+	    88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
+	    142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
+	    193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
+	    245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
+	    299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
+	    353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
+	    409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
+	    469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
+	    538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
+	    621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
+	    728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
+	    870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
+	    1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
+	    1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
+};
+
+/* the original LUT values from Alex van Kaam <darkside@chello.nl> 
+   (for via register values 12-240):
+{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
+-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
+-15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,
+-3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,
+12,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22,
+22,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33,
+33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45,
+45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60,
+61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,
+85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110};
+
+
+ Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
+ an extra term for a good fit to these inverse data!) and then 
+ solving for each temp value from -50 to 110 (the useable range for 
+ this chip).  Here's the fit: 
+ viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4 
+ - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
+ Note that n=161: */
+static const u8 viaLUT[] =
+    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+	    23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
+	    41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
+	    69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
+	    103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
+	    131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
+	    158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
+	    182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
+	    200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+	    214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
+	    225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
+	    233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+	    239, 240
+};
+
+/* Converting temps to (8-bit) hyst and over registers 
+ No interpolation here.  Just check the limits and go.
+ The +5 effectively rounds off properly and the +50 is because 
+ the temps start at -50 */
+static inline u8 TEMP_TO_REG(long val)
+{
+	return (u8)
+	    SENSORS_LIMIT(viaLUT[((val <= -500) ? 0 : (val >= 1100) ? 160 : 
+				  ((val + 5) / 10 + 50))], 0, 255);
+}
+
+/* for 8-bit temperature hyst and over registers 
+ The temp values are already *10, so we don't need to do that.
+ But we _will_ round these off to the nearest degree with (...*10+5)/10 */
+#define TEMP_FROM_REG(val) ((tempLUT[(val)]*10+5)/10)
+
+/* for 10-bit temperature readings 
+ You might _think_ this is too long to inline, but's it's really only
+ called once... */
+static inline long TEMP_FROM_REG10(u16 val)
+{
+	/* the temp values are already *10, so we don't need to do that. */
+	long temp;
+	u16 eightBits = val >> 2;
+	u16 twoBits = val & 3;
+
+	/* handle the extremes first (they won't interpolate well! ;-) */
+	if (val == 0)
+		return (long) tempLUT[0];
+	if (val == 1023)
+		return (long) tempLUT[255];
+
+	if (twoBits == 0)
+		return (long) tempLUT[eightBits];
+	else {
+		/* do some interpolation by multipying the lower and upper
+		 bounds by 25, 50 or 75, then /100. */
+		temp = ((25 * (4 - twoBits)) * tempLUT[eightBits]
+			+ (25 * twoBits) * tempLUT[eightBits + 1]);
+		/* increase the magnitude by 50 to achieve rounding. */
+		if (temp > 0)
+			temp += 50;
+		else
+			temp -= 50;
+		return (temp / 100);
+	}
+}
+
+#define ALARMS_FROM_REG(val) (val)
+
+#define DIV_FROM_REG(val) (1 << (val))
+#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
+
+/* Initial limits */
+#define VIA686A_INIT_IN_0 200
+#define VIA686A_INIT_IN_1 250
+#define VIA686A_INIT_IN_2 330
+#define VIA686A_INIT_IN_3 500
+#define VIA686A_INIT_IN_4 1200
+
+#define VIA686A_INIT_IN_PERCENTAGE 10
+
+#define VIA686A_INIT_IN_MIN_0 (VIA686A_INIT_IN_0 - VIA686A_INIT_IN_0 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_0 (VIA686A_INIT_IN_0 + VIA686A_INIT_IN_0 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_1 (VIA686A_INIT_IN_1 - VIA686A_INIT_IN_1 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_1 (VIA686A_INIT_IN_1 + VIA686A_INIT_IN_1 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_2 (VIA686A_INIT_IN_2 - VIA686A_INIT_IN_2 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_2 (VIA686A_INIT_IN_2 + VIA686A_INIT_IN_2 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_3 (VIA686A_INIT_IN_3 - VIA686A_INIT_IN_3 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_3 (VIA686A_INIT_IN_3 + VIA686A_INIT_IN_3 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MIN_4 (VIA686A_INIT_IN_4 - VIA686A_INIT_IN_4 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+#define VIA686A_INIT_IN_MAX_4 (VIA686A_INIT_IN_4 + VIA686A_INIT_IN_4 \
+        * VIA686A_INIT_IN_PERCENTAGE / 100)
+
+#define VIA686A_INIT_FAN_MIN	3000
+
+#define VIA686A_INIT_TEMP_OVER 600
+#define VIA686A_INIT_TEMP_HYST 500
+
+/* For the VIA686A, we need to keep some data in memory. That
+   data is pointed to by via686a_list[NR]->data. The structure itself is
+   dynamically allocated, at the same time when a new via686a client is
+   allocated. */
+struct via686a_data {
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u8 in[5];		/* Register value */
+	u8 in_max[5];		/* Register value */
+	u8 in_min[5];		/* Register value */
+	u8 fan[2];		/* Register value */
+	u8 fan_min[2];		/* Register value */
+	u16 temp[3];		/* Register value 10 bit */
+	u8 temp_over[3];	/* Register value */
+	u8 temp_hyst[3];	/* Register value */
+	u8 fan_div[2];		/* Register encoding, shifted right */
+	u16 alarms;		/* Register encoding, combined */
+};
+
+static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
+
+static int via686a_attach_adapter(struct i2c_adapter *adapter);
+static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
+static int via686a_detach_client(struct i2c_client *client);
+
+static int via686a_read_value(struct i2c_client *client, u8 register);
+static void via686a_write_value(struct i2c_client *client, u8 register,
+				u8 value);
+static void via686a_update_client(struct i2c_client *client);
+static void via686a_init_client(struct i2c_client *client);
+
+static int via686a_id = 0;
+
+/* The driver. I choose to use type i2c_driver, as at is identical to both
+   smbus_driver and isa_driver, and clients could be of either kind */
+static struct i2c_driver via686a_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "VIA686A",
+	.id		= I2C_DRIVERID_VIA686A,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= via686a_attach_adapter,
+	.detach_client	= via686a_detach_client,
+};
+
+
+
+/* The /proc/sys entries */
+
+/* -- SENSORS SYSCTL START -- */
+#define VIA686A_SYSCTL_IN0 1000
+#define VIA686A_SYSCTL_IN1 1001
+#define VIA686A_SYSCTL_IN2 1002
+#define VIA686A_SYSCTL_IN3 1003
+#define VIA686A_SYSCTL_IN4 1004
+#define VIA686A_SYSCTL_FAN1 1101
+#define VIA686A_SYSCTL_FAN2 1102
+#define VIA686A_SYSCTL_TEMP 1200
+#define VIA686A_SYSCTL_TEMP2 1201
+#define VIA686A_SYSCTL_TEMP3 1202
+#define VIA686A_SYSCTL_FAN_DIV 2000
+#define VIA686A_SYSCTL_ALARMS 2001
+
+#define VIA686A_ALARM_IN0 0x01
+#define VIA686A_ALARM_IN1 0x02
+#define VIA686A_ALARM_IN2 0x04
+#define VIA686A_ALARM_IN3 0x08
+#define VIA686A_ALARM_TEMP 0x10
+#define VIA686A_ALARM_FAN1 0x40
+#define VIA686A_ALARM_FAN2 0x80
+#define VIA686A_ALARM_IN4 0x100
+#define VIA686A_ALARM_TEMP2 0x800
+#define VIA686A_ALARM_CHAS 0x1000
+#define VIA686A_ALARM_TEMP3 0x8000
+
+/* -- SENSORS SYSCTL END -- */
+
+#if 0
+/* These files are created for each detected VIA686A. This is just a template;
+   though at first sight, you might think we could use a statically
+   allocated list, we need some way to get back to the parent - which
+   is done through one of the 'extra' fields which are initialized 
+   when a new copy is allocated. */
+static ctl_table via686a_dir_table_template[] = {
+	{VIA686A_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_in},
+	{VIA686A_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_in},
+	{VIA686A_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_in},
+	{VIA686A_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_in},
+	{VIA686A_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_in},
+	{VIA686A_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_fan},
+	{VIA686A_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_fan},
+	{VIA686A_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
+	 &i2c_sysctl_real, NULL, &via686a_temp},
+	{VIA686A_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
+	 &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
+	{VIA686A_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
+	 &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_temp},
+	{VIA686A_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
+	 &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_fan_div},
+	{VIA686A_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
+	 &i2c_proc_real, &i2c_sysctl_real, NULL, &via686a_alarms},
+	{0}
+};
+#endif
+
+static inline int via686a_read_value(struct i2c_client *client, u8 reg)
+{
+	return (inb_p(client->addr + reg));
+}
+
+static inline void via686a_write_value(struct i2c_client *client, u8 reg,
+				       u8 value)
+{
+	outb_p(value, client->addr + reg);
+}
+
+/* This is called when the module is loaded */
+static int via686a_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, via686a_detect);
+}
+
+static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct via686a_data *data;
+	int err = 0;
+	const char *name = "via686a";
+	u16 val;
+
+	/* Make sure we are probing the ISA bus!!  */
+	if (!i2c_is_isa_adapter(adapter)) {
+		dev_err(&adapter->dev,
+		"via686a_detect called for an I2C bus adapter?!?\n");
+		return 0;
+	}
+
+	/* 8231 requires multiple of 256, we enforce that on 686 as well */
+	if(force_addr)
+		address = force_addr & 0xFF00;
+
+	if(force_addr) {
+		dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
+			return -ENODEV;
+	}
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
+		return -ENODEV;
+	if (!(val & 0x0001)) {
+		dev_warn(&adapter->dev,"enabling sensors\n");
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+		                      val | 0x0001))
+			return -ENODEV;
+	}
+
+	/* Reserve the ISA region */
+	if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) {
+		dev_err(&adapter->dev,"region 0x%x already in use!\n",
+		       address);
+		return -ENODEV;
+	}
+
+	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+				   sizeof(struct via686a_data),
+				   GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+
+	memset(new_client,0x00, sizeof(struct i2c_client) +
+				sizeof(struct via686a_data));
+	data = (struct via686a_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &via686a_driver;
+	new_client->flags = 0;
+
+	/* Fill in the remaining client fields and put into the global list */
+	snprintf(new_client->dev.name, DEVICE_NAME_SIZE, name);
+
+	new_client->id = via686a_id++;
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto ERROR3;
+
+	/* Initialize the VIA686A chip */
+	via686a_init_client(new_client);
+	return 0;
+
+      ERROR3:
+	release_region(address, VIA686A_EXTENT);
+	kfree(new_client);
+      ERROR0:
+	return err;
+}
+
+static int via686a_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, VIA686A_EXTENT);
+	kfree(client);
+
+	return 0;
+}
+
+/* Called when we have found a new VIA686A. Set limits, etc. */
+static void via686a_init_client(struct i2c_client *client)
+{
+	int i;
+
+	/* Reset the device */
+	via686a_write_value(client, VIA686A_REG_CONFIG, 0x80);
+
+	/* Have to wait for reset to complete or else the following
+	   initializations won't work reliably. The delay was arrived at
+	   empirically, the datasheet doesn't tell you.
+	   Waiting for the reset bit to clear doesn't work, it
+	   clears in about 2-4 udelays and that isn't nearly enough. */
+	udelay(50);
+
+	via686a_write_value(client, VIA686A_REG_IN_MIN(0),
+			    IN_TO_REG(VIA686A_INIT_IN_MIN_0, 0));
+	via686a_write_value(client, VIA686A_REG_IN_MAX(0),
+			    IN_TO_REG(VIA686A_INIT_IN_MAX_0, 0));
+	via686a_write_value(client, VIA686A_REG_IN_MIN(1),
+			    IN_TO_REG(VIA686A_INIT_IN_MIN_1, 1));
+	via686a_write_value(client, VIA686A_REG_IN_MAX(1),
+			    IN_TO_REG(VIA686A_INIT_IN_MAX_1, 1));
+	via686a_write_value(client, VIA686A_REG_IN_MIN(2),
+			    IN_TO_REG(VIA686A_INIT_IN_MIN_2, 2));
+	via686a_write_value(client, VIA686A_REG_IN_MAX(2),
+			    IN_TO_REG(VIA686A_INIT_IN_MAX_2, 2));
+	via686a_write_value(client, VIA686A_REG_IN_MIN(3),
+			    IN_TO_REG(VIA686A_INIT_IN_MIN_3, 3));
+	via686a_write_value(client, VIA686A_REG_IN_MAX(3),
+			    IN_TO_REG(VIA686A_INIT_IN_MAX_3, 3));
+	via686a_write_value(client, VIA686A_REG_IN_MIN(4),
+			    IN_TO_REG(VIA686A_INIT_IN_MIN_4, 4));
+	via686a_write_value(client, VIA686A_REG_IN_MAX(4),
+			    IN_TO_REG(VIA686A_INIT_IN_MAX_4, 4));
+	via686a_write_value(client, VIA686A_REG_FAN_MIN(1),
+			    FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
+	via686a_write_value(client, VIA686A_REG_FAN_MIN(2),
+			    FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
+	for (i = 1; i <= 3; i++) {
+		via686a_write_value(client, VIA686A_REG_TEMP_OVER(i),
+				    TEMP_TO_REG(VIA686A_INIT_TEMP_OVER));
+		via686a_write_value(client, VIA686A_REG_TEMP_HYST(i),
+				    TEMP_TO_REG(VIA686A_INIT_TEMP_HYST));
+	}
+
+	/* Start monitoring */
+	via686a_write_value(client, VIA686A_REG_CONFIG, 0x01);
+
+	/* Cofigure temp interrupt mode for continuous-interrupt operation */
+	via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
+			    via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
+			    !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
+}
+
+static void via686a_update_client(struct i2c_client *client)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+           (jiffies < data->last_updated) || !data->valid) {
+
+		for (i = 0; i <= 4; i++) {
+			data->in[i] =
+			    via686a_read_value(client, VIA686A_REG_IN(i));
+			data->in_min[i] = via686a_read_value(client,
+							     VIA686A_REG_IN_MIN
+							     (i));
+			data->in_max[i] =
+			    via686a_read_value(client, VIA686A_REG_IN_MAX(i));
+		}
+		for (i = 1; i <= 2; i++) {
+			data->fan[i - 1] =
+			    via686a_read_value(client, VIA686A_REG_FAN(i));
+			data->fan_min[i - 1] = via686a_read_value(client,
+						     VIA686A_REG_FAN_MIN(i));
+		}
+		for (i = 1; i <= 3; i++) {
+			data->temp[i - 1] = via686a_read_value(client,
+						 VIA686A_REG_TEMP(i)) << 2;
+			data->temp_over[i - 1] =
+			    via686a_read_value(client,
+					       VIA686A_REG_TEMP_OVER(i));
+			data->temp_hyst[i - 1] =
+			    via686a_read_value(client,
+					       VIA686A_REG_TEMP_HYST(i));
+		}
+		/* add in lower 2 bits 
+		   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
+		   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
+		   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
+		 */
+		data->temp[0] |= (via686a_read_value(client,
+						     VIA686A_REG_TEMP_LOW1)
+				  & 0xc0) >> 6;
+		data->temp[1] |=
+		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+		     0x30) >> 4;
+		data->temp[2] |=
+		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+		     0xc0) >> 6;
+
+		i = via686a_read_value(client, VIA686A_REG_FANDIV);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = i >> 6;
+		data->alarms =
+		    via686a_read_value(client,
+				       VIA686A_REG_ALARM1) |
+		    (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+}
+
+
+/* The next few functions are the call-back functions of the /proc/sys and
+   sysctl files. Which function is used is defined in the ctl_table in
+   the extra1 field.
+   Each function must return the magnitude (power of 10 to divide the date
+   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
+   put a maximum of *nrels elements in results reflecting the data of this
+   file, and set *nrels to the number it actually put in it, if operation==
+   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
+   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
+   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
+   large enough (by checking the incoming value of *nrels). This is not very
+   good practice, but as long as you put less than about 5 values in results,
+   you can assume it is large enough. */
+/* FIXME, remove these functions, they are here to verify the sysfs conversion
+ * is correct, or not */
+__attribute__((unused))
+static void via686a_in(struct i2c_client *client, int operation, int ctl_name,
+               int *nrels_mag, long *results)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	int nr = ctl_name - VIA686A_SYSCTL_IN0;
+
+	if (operation == SENSORS_PROC_REAL_INFO)
+		*nrels_mag = 2;
+	else if (operation == SENSORS_PROC_REAL_READ) {
+		via686a_update_client(client);
+		results[0] = IN_FROM_REG(data->in_min[nr], nr);
+		results[1] = IN_FROM_REG(data->in_max[nr], nr);
+		results[2] = IN_FROM_REG(data->in[nr], nr);
+		*nrels_mag = 3;
+	} else if (operation == SENSORS_PROC_REAL_WRITE) {
+		if (*nrels_mag >= 1) {
+			data->in_min[nr] = IN_TO_REG(results[0], nr);
+			via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
+					    data->in_min[nr]);
+		}
+		if (*nrels_mag >= 2) {
+			data->in_max[nr] = IN_TO_REG(results[1], nr);
+			via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
+					    data->in_max[nr]);
+		}
+	}
+}
+
+__attribute__((unused))
+static void via686a_fan(struct i2c_client *client, int operation, int ctl_name,
+		 int *nrels_mag, long *results)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	int nr = ctl_name - VIA686A_SYSCTL_FAN1 + 1;
+
+	if (operation == SENSORS_PROC_REAL_INFO)
+		*nrels_mag = 0;
+	else if (operation == SENSORS_PROC_REAL_READ) {
+		via686a_update_client(client);
+		results[0] = FAN_FROM_REG(data->fan_min[nr - 1],
+					  DIV_FROM_REG(data->fan_div
+						       [nr - 1]));
+		results[1] = FAN_FROM_REG(data->fan[nr - 1],
+				 DIV_FROM_REG(data->fan_div[nr - 1]));
+		*nrels_mag = 2;
+	} else if (operation == SENSORS_PROC_REAL_WRITE) {
+		if (*nrels_mag >= 1) {
+			data->fan_min[nr - 1] = FAN_TO_REG(results[0], 
+							   DIV_FROM_REG(data->
+							      fan_div[nr -1]));
+			via686a_write_value(client,
+					    VIA686A_REG_FAN_MIN(nr),
+					    data->fan_min[nr - 1]);
+		}
+	}
+}
+
+__attribute__((unused))
+static void via686a_temp(struct i2c_client *client, int operation, int ctl_name,
+		  int *nrels_mag, long *results)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	int nr = ctl_name - VIA686A_SYSCTL_TEMP;
+
+	if (operation == SENSORS_PROC_REAL_INFO)
+		*nrels_mag = 1;
+	else if (operation == SENSORS_PROC_REAL_READ) {
+		via686a_update_client(client);
+		results[0] = TEMP_FROM_REG(data->temp_over[nr]);
+		results[1] = TEMP_FROM_REG(data->temp_hyst[nr]);
+		results[2] = TEMP_FROM_REG10(data->temp[nr]);
+		*nrels_mag = 3;
+	} else if (operation == SENSORS_PROC_REAL_WRITE) {
+		if (*nrels_mag >= 1) {
+			data->temp_over[nr] = TEMP_TO_REG(results[0]);
+			via686a_write_value(client,
+					    VIA686A_REG_TEMP_OVER(nr + 1),
+					    data->temp_over[nr]);
+		}
+		if (*nrels_mag >= 2) {
+			data->temp_hyst[nr] = TEMP_TO_REG(results[1]);
+			via686a_write_value(client,
+					    VIA686A_REG_TEMP_HYST(nr + 1),
+					    data->temp_hyst[nr]);
+		}
+	}
+}
+
+__attribute__((unused))
+static void via686a_alarms(struct i2c_client *client, int operation, int ctl_name,
+		    int *nrels_mag, long *results)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	if (operation == SENSORS_PROC_REAL_INFO)
+		*nrels_mag = 0;
+	else if (operation == SENSORS_PROC_REAL_READ) {
+		via686a_update_client(client);
+		results[0] = ALARMS_FROM_REG(data->alarms);
+		*nrels_mag = 1;
+	}
+}
+
+__attribute__((unused))
+static void via686a_fan_div(struct i2c_client *client, int operation,
+		     int ctl_name, int *nrels_mag, long *results)
+{
+	struct via686a_data *data = i2c_get_clientdata(client);
+	int old;
+
+	if (operation == SENSORS_PROC_REAL_INFO)
+		*nrels_mag = 0;
+	else if (operation == SENSORS_PROC_REAL_READ) {
+		via686a_update_client(client);
+		results[0] = DIV_FROM_REG(data->fan_div[0]);
+		results[1] = DIV_FROM_REG(data->fan_div[1]);
+		*nrels_mag = 2;
+	} else if (operation == SENSORS_PROC_REAL_WRITE) {
+		old = via686a_read_value(client, VIA686A_REG_FANDIV);
+		if (*nrels_mag >= 2) {
+			data->fan_div[1] = DIV_TO_REG(results[1]);
+			old = (old & 0x3f) | (data->fan_div[1] << 6);
+		}
+		if (*nrels_mag >= 1) {
+			data->fan_div[0] = DIV_TO_REG(results[0]);
+			old = (old & 0xcf) | (data->fan_div[0] << 4);
+			via686a_write_value(client, VIA686A_REG_FANDIV,
+					    old);
+		}
+	}
+}
+
+
+static struct pci_device_id via686a_pci_ids[] __devinitdata = {
+       {
+	       .vendor 		= PCI_VENDOR_ID_VIA, 
+	       .device 		= PCI_DEVICE_ID_VIA_82C686_4, 
+	       .subvendor	= PCI_ANY_ID, 
+	       .subdevice	= PCI_ANY_ID, 
+	       .class		= 0, 
+	       .class_mask	= 0, 
+	       .driver_data	= 0, 
+       },
+       { 0, }
+};
+
+static int __devinit via686a_pci_probe(struct pci_dev *dev,
+                                      const struct pci_device_id *id)
+{
+       u16 val;
+       int addr = 0;
+
+       if (PCIBIOS_SUCCESSFUL !=
+           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+               return -ENODEV;
+
+       addr = val & ~(VIA686A_EXTENT - 1);
+       if (addr == 0 && force_addr == 0) {
+               dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
+               return -ENODEV;
+       }
+       if (force_addr)
+               addr = force_addr;      /* so detect will get called */
+
+       if (!addr) {
+               dev_err(&dev->dev,"No Via 686A sensors found.\n");
+               return -ENODEV;
+       }
+       normal_isa[0] = addr;
+       s_bridge = dev;
+       return i2c_add_driver(&via686a_driver);
+}
+
+static void __devexit via686a_pci_remove(struct pci_dev *dev)
+{
+       i2c_del_driver(&via686a_driver);
+}
+
+static struct pci_driver via686a_pci_driver = {
+       .name		= "via686a",
+       .id_table	= via686a_pci_ids,
+       .probe		= via686a_pci_probe,
+       .remove		= __devexit_p(via686a_pci_remove),
+};
+
+static int __init sm_via686a_init(void)
+{
+       return pci_module_init(&via686a_pci_driver);
+}
+
+static void __exit sm_via686a_exit(void)
+{
+       pci_unregister_driver(&via686a_pci_driver);
+}
+
+MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+              "Mark Studebaker <mdsxyz123@yahoo.com> "
+             "and Bob Dougherty <bobd@stanford.edu>");
+MODULE_DESCRIPTION("VIA 686A Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(sm_via686a_init);
+module_exit(sm_via686a_exit);
diff -urN linux-2.5.66-bk8/drivers/i2c/chips/w83781d.c linux-2.5.66-bk9/drivers/i2c/chips/w83781d.c
--- linux-2.5.66-bk8/drivers/i2c/chips/w83781d.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/chips/w83781d.c	2003-04-03 04:32:42.000000000 -0800
@@ -0,0 +1,1882 @@
+/*
+    w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>,
+    and Mark 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.
+*/
+
+/*
+    Supports following chips:
+
+    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
+    as99127f	7	3	1?	3	0x30	0x12c3	yes	no
+    asb100 "bach" (type_name = as99127f)	0x30	0x0694	yes	no
+    w83781d	7	3	0	3	0x10	0x5ca3	yes	yes
+    w83627hf	9	3	2	3	0x20	0x5ca3	yes	yes(LPC)
+    w83782d	9	3	2-4	3	0x30	0x5ca3	yes	yes
+    w83783s	5-6	3	2	1-2	0x40	0x5ca3	yes	no
+    w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+#include <asm/io.h>
+
+/* RT Table support #defined so we can take it out if it gets bothersome */
+#define W83781D_RT			1
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { 0x20, 0x2f, SENSORS_I2C_END };
+static unsigned int normal_isa[] = { 0x0290, SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf);
+SENSORS_MODULE_PARM(force_subclients, "List of subclient addresses: "
+		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init = 1;
+MODULE_PARM(init, "i");
+MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
+
+/* Constants specified below */
+
+/* Length of ISA address segment */
+#define W83781D_EXTENT			8
+
+/* Where are the ISA address/data registers relative to the base address */
+#define W83781D_ADDR_REG_OFFSET		5
+#define W83781D_DATA_REG_OFFSET		6
+
+/* The W83781D registers */
+/* The W83782D registers for nr=7,8 are in bank 5 */
+#define W83781D_REG_IN_MAX(nr)		((nr < 7) ? (0x2b + (nr) * 2) : \
+						    (0x554 + (((nr) - 7) * 2)))
+#define W83781D_REG_IN_MIN(nr)		((nr < 7) ? (0x2c + (nr) * 2) : \
+						    (0x555 + (((nr) - 7) * 2)))
+#define W83781D_REG_IN(nr)		((nr < 7) ? (0x20 + (nr)) : \
+						    (0x550 + (nr) - 7))
+
+#define W83781D_REG_FAN_MIN(nr)		(0x3a + (nr))
+#define W83781D_REG_FAN(nr)		(0x27 + (nr))
+
+#define W83781D_REG_BANK		0x4E
+#define W83781D_REG_TEMP2_CONFIG	0x152
+#define W83781D_REG_TEMP3_CONFIG	0x252
+#define W83781D_REG_TEMP(nr)		((nr == 3) ? (0x0250) : \
+					((nr == 2) ? (0x0150) : \
+						     (0x27)))
+#define W83781D_REG_TEMP_HYST(nr)	((nr == 3) ? (0x253) : \
+					((nr == 2) ? (0x153) : \
+						     (0x3A)))
+#define W83781D_REG_TEMP_OVER(nr)	((nr == 3) ? (0x255) : \
+					((nr == 2) ? (0x155) : \
+						     (0x39)))
+
+#define W83781D_REG_CONFIG		0x40
+#define W83781D_REG_ALARM1		0x41
+#define W83781D_REG_ALARM2		0x42
+#define W83781D_REG_ALARM3		0x450	/* not on W83781D */
+
+#define W83781D_REG_IRQ			0x4C
+#define W83781D_REG_BEEP_CONFIG		0x4D
+#define W83781D_REG_BEEP_INTS1		0x56
+#define W83781D_REG_BEEP_INTS2		0x57
+#define W83781D_REG_BEEP_INTS3		0x453	/* not on W83781D */
+
+#define W83781D_REG_VID_FANDIV		0x47
+
+#define W83781D_REG_CHIPID		0x49
+#define W83781D_REG_WCHIPID		0x58
+#define W83781D_REG_CHIPMAN		0x4F
+#define W83781D_REG_PIN			0x4B
+
+/* 782D/783S only */
+#define W83781D_REG_VBAT		0x5D
+
+/* PWM 782D (1-4) and 783S (1-2) only */
+#define W83781D_REG_PWM1		0x5B	/* 782d and 783s/627hf datasheets disagree */
+						/* on which is which; */
+#define W83781D_REG_PWM2		0x5A	/* We follow the 782d convention here, */
+						/* However 782d is probably wrong. */
+#define W83781D_REG_PWM3		0x5E
+#define W83781D_REG_PWM4		0x5F
+#define W83781D_REG_PWMCLK12		0x5C
+#define W83781D_REG_PWMCLK34		0x45C
+static const u8 regpwm[] = { W83781D_REG_PWM1, W83781D_REG_PWM2,
+	W83781D_REG_PWM3, W83781D_REG_PWM4
+};
+
+#define W83781D_REG_PWM(nr)		(regpwm[(nr) - 1])
+
+#define W83781D_REG_I2C_ADDR		0x48
+#define W83781D_REG_I2C_SUBADDR		0x4A
+
+/* The following are undocumented in the data sheets however we
+   received the information in an email from Winbond tech support */
+/* Sensor selection - not on 781d */
+#define W83781D_REG_SCFG1		0x5D
+static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 };
+
+#define W83781D_REG_SCFG2		0x59
+static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
+
+#define W83781D_DEFAULT_BETA		3435
+
+/* RT Table registers */
+#define W83781D_REG_RT_IDX		0x50
+#define W83781D_REG_RT_VAL		0x51
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+   variants. Note that you should be a bit careful with which arguments
+   these macros are called: arguments may be evaluated more than once.
+   Fixing this is just not worth it. */
+#define IN_TO_REG(val)			(SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
+#define IN_FROM_REG(val)		(((val) * 16) / 10)
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+	if (rpm == 0)
+		return 255;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)		((val) == 0   ? -1 : \
+					((val) == 255 ? 0 : \
+							1350000 / ((val) * (div))))
+
+#define TEMP_TO_REG(val)		(SENSORS_LIMIT(((val / 10) < 0 ? (((val / 10) - 5) / 10) : \
+									 ((val / 10) + 5) / 10), 0, 255))
+#define TEMP_FROM_REG(val)		((((val ) > 0x80 ? (val) - 0x100 : (val)) * 10) * 10)
+
+#define TEMP_ADD_TO_REG(val)		(SENSORS_LIMIT(((((val / 10) + 2) / 5) << 7),\
+                                              0, 0xffff))
+#define TEMP_ADD_FROM_REG(val)		((((val) >> 7) * 5) * 10)
+
+#define AS99127_TEMP_ADD_TO_REG(val)	(SENSORS_LIMIT((((((val / 10) + 2)*4)/10) \
+                                               << 7), 0, 0xffff))
+#define AS99127_TEMP_ADD_FROM_REG(val)	(((((val) >> 7) * 10) / 4) * 10)
+
+#define ALARMS_FROM_REG(val)		(val)
+#define PWM_FROM_REG(val)		(val)
+#define PWM_TO_REG(val)			(SENSORS_LIMIT((val),0,255))
+#define BEEP_MASK_FROM_REG(val)		(val)
+#define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
+
+#define BEEP_ENABLE_TO_REG(val)		((val) ? 1 : 0)
+#define BEEP_ENABLE_FROM_REG(val)	((val) ? 1 : 0)
+
+#define DIV_FROM_REG(val)		(1 << (val))
+
+static inline u8
+DIV_TO_REG(long val, enum chips type)
+{
+	int i;
+	val = SENSORS_LIMIT(val, 1,
+			    ((type == w83781d
+			      || type == as99127f) ? 8 : 128)) >> 1;
+	for (i = 0; i < 6; i++) {
+		if (val == 0)
+			break;
+		val >>= 1;
+	}
+	return ((u8) i);
+}
+
+/* Initial limits */
+#define W83781D_INIT_IN_0		(vid == 3500 ? 280 : vid / 10)
+#define W83781D_INIT_IN_1		(vid == 3500 ? 280 : vid / 10)
+#define W83781D_INIT_IN_2		330
+#define W83781D_INIT_IN_3		(((500)   * 100) / 168)
+#define W83781D_INIT_IN_4		(((1200)  * 10) / 38)
+#define W83781D_INIT_IN_5		(((-1200) * -604) / 2100)
+#define W83781D_INIT_IN_6		(((-500)  * -604) / 909)
+#define W83781D_INIT_IN_7		(((500)   * 100) / 168)
+#define W83781D_INIT_IN_8		300
+/* Initial limits for 782d/783s negative voltages */
+/* Note level shift. Change min/max below if you change these. */
+#define W83782D_INIT_IN_5		((((-1200) + 1491) * 100)/514)
+#define W83782D_INIT_IN_6		((( (-500)  + 771) * 100)/314)
+
+#define W83781D_INIT_IN_PERCENTAGE	10
+#define W83781D_INIT_IN_MIN(val)	(val - val * W83781D_INIT_IN_PERCENTAGE / 100)
+#define W83781D_INIT_IN_MAX(val)	(val + val * W83781D_INIT_IN_PERCENTAGE / 100)
+
+#define W83781D_INIT_IN_MIN_0		W83781D_INIT_IN_MIN(W83781D_INIT_IN_0)
+#define W83781D_INIT_IN_MAX_0		W83781D_INIT_IN_MAX(W83781D_INIT_IN_0)
+#define W83781D_INIT_IN_MIN_1		W83781D_INIT_IN_MIN(W83781D_INIT_IN_1)
+#define W83781D_INIT_IN_MAX_1		W83781D_INIT_IN_MAX(W83781D_INIT_IN_1)
+#define W83781D_INIT_IN_MIN_2		W83781D_INIT_IN_MIN(W83781D_INIT_IN_2)
+#define W83781D_INIT_IN_MAX_2		W83781D_INIT_IN_MAX(W83781D_INIT_IN_2)
+#define W83781D_INIT_IN_MIN_3		W83781D_INIT_IN_MIN(W83781D_INIT_IN_3)
+#define W83781D_INIT_IN_MAX_3		W83781D_INIT_IN_MAX(W83781D_INIT_IN_3)
+#define W83781D_INIT_IN_MIN_4		W83781D_INIT_IN_MIN(W83781D_INIT_IN_4)
+#define W83781D_INIT_IN_MAX_4		W83781D_INIT_IN_MAX(W83781D_INIT_IN_4)
+#define W83781D_INIT_IN_MIN_5		W83781D_INIT_IN_MIN(W83781D_INIT_IN_5)
+#define W83781D_INIT_IN_MAX_5		W83781D_INIT_IN_MAX(W83781D_INIT_IN_5)
+#define W83781D_INIT_IN_MIN_6		W83781D_INIT_IN_MIN(W83781D_INIT_IN_6)
+#define W83781D_INIT_IN_MAX_6		W83781D_INIT_IN_MAX(W83781D_INIT_IN_6)
+#define W83781D_INIT_IN_MIN_7		W83781D_INIT_IN_MIN(W83781D_INIT_IN_7)
+#define W83781D_INIT_IN_MAX_7		W83781D_INIT_IN_MAX(W83781D_INIT_IN_7)
+#define W83781D_INIT_IN_MIN_8		W83781D_INIT_IN_MIN(W83781D_INIT_IN_8)
+#define W83781D_INIT_IN_MAX_8		W83781D_INIT_IN_MAX(W83781D_INIT_IN_8)
+
+/* Initial limits for 782d/783s negative voltages */
+/* These aren't direct multiples because of level shift */
+/* Beware going negative - check */
+#define W83782D_INIT_IN_MIN_5_TMP \
+	(((-1200 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
+#define W83782D_INIT_IN_MIN_5 \
+	((W83782D_INIT_IN_MIN_5_TMP > 0) ? W83782D_INIT_IN_MIN_5_TMP : 0)
+#define W83782D_INIT_IN_MAX_5 \
+	(((-1200 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
+#define W83782D_INIT_IN_MIN_6_TMP \
+	((( -500 * (100 + W83781D_INIT_IN_PERCENTAGE)) +  (771 * 100))/314)
+#define W83782D_INIT_IN_MIN_6 \
+	((W83782D_INIT_IN_MIN_6_TMP > 0) ? W83782D_INIT_IN_MIN_6_TMP : 0)
+#define W83782D_INIT_IN_MAX_6 \
+	((( -500 * (100 - W83781D_INIT_IN_PERCENTAGE)) +  (771 * 100))/314)
+
+#define W83781D_INIT_FAN_MIN_1		3000
+#define W83781D_INIT_FAN_MIN_2		3000
+#define W83781D_INIT_FAN_MIN_3		3000
+
+/* temp = value / 100 */
+#define W83781D_INIT_TEMP_OVER		6000
+#define W83781D_INIT_TEMP_HYST		12700	/* must be 127 for ALARM to work */
+#define W83781D_INIT_TEMP2_OVER		6000
+#define W83781D_INIT_TEMP2_HYST		5000
+#define W83781D_INIT_TEMP3_OVER		6000
+#define W83781D_INIT_TEMP3_HYST		5000
+
+/* There are some complications in a module like this. First off, W83781D chips
+   may be both present on the SMBus and the ISA bus, and we have to handle
+   those cases separately at some places. Second, there might be several
+   W83781D chips available (well, actually, that is probably never done; but
+   it is a clean illustration of how to handle a case like that). Finally,
+   a specific chip may be attached to *both* ISA and SMBus, and we would
+   not like to detect it double. Fortunately, in the case of the W83781D at
+   least, a register tells us what SMBus address we are on, so that helps
+   a bit - except if there could be more than one SMBus. Groan. No solution
+   for this yet. */
+
+/* This module may seem overly long and complicated. In fact, it is not so
+   bad. Quite a lot of bookkeeping is done. A real driver can often cut
+   some corners. */
+
+/* For each registered W83781D, we need to keep some data in memory. That
+   data is pointed to by w83781d_list[NR]->data. The structure itself is
+   dynamically allocated, at the same time when a new w83781d client is
+   allocated. */
+struct w83781d_data {
+	struct semaphore lock;
+	enum chips type;
+
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	struct i2c_client *lm75;	/* for secondary I2C addresses */
+	/* pointer to array of 2 subclients */
+
+	u8 in[9];		/* Register value - 8 & 9 for 782D only */
+	u8 in_max[9];		/* Register value - 8 & 9 for 782D only */
+	u8 in_min[9];		/* Register value - 8 & 9 for 782D only */
+	u8 fan[3];		/* Register value */
+	u8 fan_min[3];		/* Register value */
+	u8 temp;
+	u8 temp_min;		/* Register value */
+	u8 temp_max;		/* Register value */
+	u16 temp_add[2];	/* Register value */
+	u16 temp_max_add[2];	/* Register value */
+	u16 temp_min_add[2];	/* Register value */
+	u8 fan_div[3];		/* Register encoding, shifted right */
+	u8 vid;			/* Register encoding, combined */
+	u32 alarms;		/* Register encoding, combined */
+	u32 beep_mask;		/* Register encoding, combined */
+	u8 beep_enable;		/* Boolean */
+	u8 pwm[4];		/* Register value */
+	u8 pwmenable[4];	/* Boolean */
+	u16 sens[3];		/* 782D/783S only.
+				   1 = pentium diode; 2 = 3904 diode;
+				   3000-5000 = thermistor beta.
+				   Default = 3435. 
+				   Other Betas unimplemented */
+#ifdef W83781D_RT
+	u8 rt[3][32];		/* Register value */
+#endif
+	u8 vrm;
+};
+
+static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83781d_detach_client(struct i2c_client *client);
+
+static int w83781d_read_value(struct i2c_client *client, u16 register);
+static int w83781d_write_value(struct i2c_client *client, u16 register,
+			       u16 value);
+static void w83781d_update_client(struct i2c_client *client);
+static void w83781d_init_client(struct i2c_client *client);
+
+static inline u16 swap_bytes(u16 val)
+{
+	return (val >> 8) | (val << 8);
+}
+
+static struct i2c_driver w83781d_driver = {
+	.owner = THIS_MODULE,
+	.name = "w83781d",
+	.id = I2C_DRIVERID_W83781D,
+	.flags = I2C_DF_NOTIFY,
+	.attach_adapter = w83781d_attach_adapter,
+	.detach_client = w83781d_detach_client,
+};
+
+/* following are the sysfs callback functions */
+#define show_in_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	 \
+	w83781d_update_client(client); \
+	 \
+	return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr])); \
+}
+show_in_reg(in);
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	u32 val; \
+	 \
+	val = simple_strtoul(buf, NULL, 10); \
+	data->in_##reg[nr] = IN_TO_REG(val); \
+	w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
+	 \
+	return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_offset(offset) \
+static ssize_t \
+show_regs_in_##offset (struct device *dev, char *buf) \
+{ \
+        return show_in(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(in_input##offset, S_IRUGO, show_regs_in_##offset, NULL)
+
+#define sysfs_in_reg_offset(reg, offset) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+{ \
+	return show_in_##reg (dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_in_##reg (dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(in_##reg##offset, S_IRUGO| S_IWUSR, show_regs_in_##reg##offset, store_regs_in_##reg##offset)
+
+#define sysfs_in_offsets(offset) \
+sysfs_in_offset(offset); \
+sysfs_in_reg_offset(min, offset); \
+sysfs_in_reg_offset(max, offset);
+
+sysfs_in_offsets(0);
+sysfs_in_offsets(1);
+sysfs_in_offsets(2);
+sysfs_in_offsets(3);
+sysfs_in_offsets(4);
+sysfs_in_offsets(5);
+sysfs_in_offsets(6);
+sysfs_in_offsets(7);
+sysfs_in_offsets(8);
+
+#define device_create_file_in(client, offset) \
+device_create_file(&client->dev, &dev_attr_in_input##offset); \
+device_create_file(&client->dev, &dev_attr_in_min##offset); \
+device_create_file(&client->dev, &dev_attr_in_max##offset);
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	 \
+	w83781d_update_client(client); \
+	 \
+	return sprintf(buf,"%ld\n", \
+		FAN_FROM_REG(data->reg[nr-1], (long)DIV_FROM_REG(data->fan_div[nr-1]))); \
+}
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->fan_min[nr - 1] =
+	    FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1]));
+	w83781d_write_value(client, W83781D_REG_FAN_MIN(nr),
+			    data->fan_min[nr - 1]);
+
+	return count;
+}
+
+#define sysfs_fan_offset(offset) \
+static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+{ \
+	return show_fan(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(fan_input##offset, S_IRUGO, show_regs_fan_##offset, NULL)
+
+#define sysfs_fan_min_offset(offset) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+{ \
+	return show_fan_min(dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_fan_min(dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(fan_min##offset, S_IRUGO | S_IWUSR, show_regs_fan_min##offset, store_regs_fan_min##offset)
+
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
+
+#define device_create_file_fan(client, offset) \
+device_create_file(&client->dev, &dev_attr_fan_input##offset); \
+device_create_file(&client->dev, &dev_attr_fan_min##offset); \
+
+#define show_temp_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	 \
+	w83781d_update_client(client); \
+	 \
+	if (nr >= 2) {	/* TEMP2 and TEMP3 */ \
+		if (data->type == as99127f) { \
+			return sprintf(buf,"%ld\n", \
+				(long)AS99127_TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \
+		} else { \
+			return sprintf(buf,"%ld\n", \
+				(long)TEMP_ADD_FROM_REG(data->reg##_add[nr-2])); \
+		} \
+	} else {	/* TEMP1 */ \
+		return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
+	} \
+}
+show_temp_reg(temp);
+show_temp_reg(temp_min);
+show_temp_reg(temp_max);
+
+#define store_temp_reg(REG, reg) \
+static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	u32 val; \
+	 \
+	val = simple_strtoul(buf, NULL, 10); \
+	 \
+	if (nr >= 2) {	/* TEMP2 and TEMP3 */ \
+		if (data->type == as99127f) \
+			data->temp_##reg##_add[nr-2] = AS99127_TEMP_ADD_TO_REG(val); \
+		else \
+			data->temp_##reg##_add[nr-2] = TEMP_ADD_TO_REG(val); \
+		 \
+		w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+				data->temp_##reg##_add[nr-2]); \
+	} else {	/* TEMP1 */ \
+		data->temp_##reg = TEMP_TO_REG(val); \
+		w83781d_write_value(client, W83781D_REG_TEMP_##REG(nr), \
+			data->temp_##reg); \
+	} \
+	 \
+	return count; \
+}
+store_temp_reg(OVER, min);
+store_temp_reg(HYST, max);
+
+#define sysfs_temp_offset(offset) \
+static ssize_t \
+show_regs_temp_##offset (struct device *dev, char *buf) \
+{ \
+	return show_temp(dev, buf, 0x##offset); \
+} \
+static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_regs_temp_##offset, NULL)
+
+#define sysfs_temp_reg_offset(reg, offset) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+{ \
+	return show_temp_##reg (dev, buf, 0x##offset); \
+} \
+static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_temp_##reg (dev, buf, count, 0x##offset); \
+} \
+static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##offset, store_regs_temp_##reg##offset)
+
+#define sysfs_temp_offsets(offset) \
+sysfs_temp_offset(offset); \
+sysfs_temp_reg_offset(min, offset); \
+sysfs_temp_reg_offset(max, offset);
+
+sysfs_temp_offsets(1);
+sysfs_temp_offsets(2);
+sysfs_temp_offsets(3);
+
+#define device_create_file_temp(client, offset) \
+device_create_file(&client->dev, &dev_attr_temp_input##offset); \
+device_create_file(&client->dev, &dev_attr_temp_max##offset); \
+device_create_file(&client->dev, &dev_attr_temp_min##offset);
+
+static ssize_t
+show_vid_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+
+static
+DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL)
+#define device_create_file_vid(client) \
+device_create_file(&client->dev, &dev_attr_vid);
+static ssize_t
+show_vrm_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	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 w83781d_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_alarms_reg(struct device *dev, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL)
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+#define show_beep_reg(REG, reg) \
+static ssize_t show_beep_##reg (struct device *dev, char *buf) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83781d_data *data = i2c_get_clientdata(client); \
+	 \
+	w83781d_update_client(client); \
+	 \
+	return sprintf(buf,"%ld\n", (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \
+}
+show_beep_reg(ENABLE, enable);
+show_beep_reg(MASK, mask);
+
+#define BEEP_ENABLE			0	/* Store beep_enable */
+#define BEEP_MASK			1	/* Store beep_mask */
+
+static ssize_t
+store_beep_reg(struct device *dev, const char *buf, size_t count,
+	       int update_mask)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val, val2;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	if (update_mask == BEEP_MASK) {	/* We are storing beep_mask */
+		data->beep_mask = BEEP_MASK_TO_REG(val);
+		w83781d_write_value(client, W83781D_REG_BEEP_INTS1,
+				    data->beep_mask & 0xff);
+
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			w83781d_write_value(client, W83781D_REG_BEEP_INTS3,
+					    ((data->beep_mask) >> 16) & 0xff);
+		}
+
+		val2 = (data->beep_mask >> 8) & 0x7f;
+	} else {		/* We are storing beep_enable */
+		val2 = w83781d_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f;
+		data->beep_enable = BEEP_ENABLE_TO_REG(val);
+	}
+
+	w83781d_write_value(client, W83781D_REG_BEEP_INTS2,
+			    val2 | data->beep_enable << 7);
+
+	return count;
+}
+
+#define sysfs_beep(REG, reg) \
+static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+{ \
+	return show_beep_##reg(dev, buf); \
+} \
+static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_beep_reg(dev, buf, count, BEEP_##REG); \
+} \
+static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_regs_beep_##reg)
+
+sysfs_beep(ENABLE, enable);
+sysfs_beep(MASK, mask);
+
+#define device_create_file_beep(client) \
+device_create_file(&client->dev, &dev_attr_beep_enable); \
+device_create_file(&client->dev, &dev_attr_beep_mask);
+
+/* w83697hf only has two fans */
+static ssize_t
+show_fan_div_reg(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n",
+		       (long) DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* w83697hf only has two fans */
+static ssize_t
+store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val, old, old2, old3;
+
+	val = simple_strtoul(buf, NULL, 10);
+	old = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
+
+	data->fan_div[nr - 1] = DIV_TO_REG(val, data->type);
+
+	/* w83781d and as99127f don't have extended divisor bits */
+	if ((data->type != w83781d) && data->type != as99127f) {
+		old3 = w83781d_read_value(client, W83781D_REG_VBAT);
+	}
+	if (nr >= 3 && data->type != w83697hf) {
+		old2 = w83781d_read_value(client, W83781D_REG_PIN);
+		old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
+		w83781d_write_value(client, W83781D_REG_PIN, old2);
+
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
+		}
+	}
+	if (nr >= 2) {
+		old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
+
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
+		}
+	}
+	if (nr >= 1) {
+		old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
+		w83781d_write_value(client, W83781D_REG_VID_FANDIV, old);
+
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
+			w83781d_write_value(client, W83781D_REG_VBAT, old3);
+		}
+	}
+
+	return count;
+}
+
+#define sysfs_fan_div(offset) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+{ \
+	return show_fan_div_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_fan_div_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
+
+sysfs_fan_div(1);
+sysfs_fan_div(2);
+sysfs_fan_div(3);
+
+#define device_create_file_fan_div(client, offset) \
+device_create_file(&client->dev, &dev_attr_fan_div##offset); \
+
+/* w83697hf only has two fans */
+static ssize_t
+show_pwm_reg(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
+}
+
+/* w83697hf only has two fans */
+static ssize_t
+show_pwmenable_reg(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n", (long) data->pwmenable[nr - 1]);
+}
+
+static ssize_t
+store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	data->pwm[nr - 1] = PWM_TO_REG(val);
+	w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]);
+
+	return count;
+}
+
+static ssize_t
+store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val, j, k;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	/* only PWM2 can be enabled/disabled */
+	if (nr == 2) {
+		j = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+		k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
+
+		if (val > 0) {
+			if (!(j & 0x08))
+				w83781d_write_value(client,
+						    W83781D_REG_PWMCLK12,
+						    j | 0x08);
+			if (k & 0x10)
+				w83781d_write_value(client,
+						    W83781D_REG_BEEP_CONFIG,
+						    k & 0xef);
+
+			data->pwmenable[1] = 1;
+		} else {
+			if (j & 0x08)
+				w83781d_write_value(client,
+						    W83781D_REG_PWMCLK12,
+						    j & 0xf7);
+			if (!(k & 0x10))
+				w83781d_write_value(client,
+						    W83781D_REG_BEEP_CONFIG,
+						    j | 0x10);
+
+			data->pwmenable[1] = 0;
+		}
+	}
+
+	return count;
+}
+
+#define sysfs_pwm(offset) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+{ \
+	return show_pwm_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_pwm_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, show_regs_pwm_##offset, store_regs_pwm_##offset)
+
+#define sysfs_pwmenable(offset) \
+static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
+{ \
+	return show_pwmenable_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_pwmenable_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_pwmenable_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(pwm_enable##offset, S_IRUGO | S_IWUSR, show_regs_pwmenable_##offset, store_regs_pwmenable_##offset)
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwmenable(2);		/* only PWM2 can be enabled/disabled */
+sysfs_pwm(3);
+sysfs_pwm(4);
+
+#define device_create_file_pwm(client, offset) \
+device_create_file(&client->dev, &dev_attr_pwm##offset); \
+
+#define device_create_file_pwmenable(client, offset) \
+device_create_file(&client->dev, &dev_attr_pwm_enable##offset); \
+
+static ssize_t
+show_sensor_reg(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+
+	w83781d_update_client(client);
+
+	return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]);
+}
+
+static ssize_t
+store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val, tmp;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	switch (val) {
+	case 1:		/* PII/Celeron diode */
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+		w83781d_write_value(client, W83781D_REG_SCFG1,
+				    tmp | BIT_SCFG1[nr - 1]);
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
+		w83781d_write_value(client, W83781D_REG_SCFG2,
+				    tmp | BIT_SCFG2[nr - 1]);
+		data->sens[nr - 1] = val;
+		break;
+	case 2:		/* 3904 */
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+		w83781d_write_value(client, W83781D_REG_SCFG1,
+				    tmp | BIT_SCFG1[nr - 1]);
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG2);
+		w83781d_write_value(client, W83781D_REG_SCFG2,
+				    tmp & ~BIT_SCFG2[nr - 1]);
+		data->sens[nr - 1] = val;
+		break;
+	case W83781D_DEFAULT_BETA:	/* thermistor */
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+		w83781d_write_value(client, W83781D_REG_SCFG1,
+				    tmp & ~BIT_SCFG1[nr - 1]);
+		data->sens[nr - 1] = val;
+		break;
+	default:
+		dev_err(&client->dev,
+		       "Invalid sensor type %ld; must be 1, 2, or %d\n",
+		       (long) val, W83781D_DEFAULT_BETA);
+		break;
+	}
+
+	return count;
+}
+
+#define sysfs_sensor(offset) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+{ \
+    return show_sensor_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+    return store_sensor_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, show_regs_sensor_##offset, store_regs_sensor_##offset)
+
+sysfs_sensor(1);
+sysfs_sensor(2);
+sysfs_sensor(3);
+
+#define device_create_file_sensor(client, offset) \
+device_create_file(&client->dev, &dev_attr_sensor##offset); \
+
+#ifdef W83781D_RT
+static ssize_t
+show_rt_reg(struct device *dev, char *buf, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int i, j = 0;
+
+	w83781d_update_client(client);
+
+	for (i = 0; i < 32; i++) {
+		if (i > 0)
+			j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
+		else
+			j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]);
+	}
+	j += sprintf(buf, "\n");
+
+	return j;
+}
+
+static ssize_t
+store_rt_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	u32 val, i;
+
+	for (i = 0; i < count; i++) {
+		val = simple_strtoul(buf + count, NULL, 10);
+
+		/* fixme: no bounds checking 0-255 */
+		data->rt[nr - 1][i] = val & 0xff;
+		w83781d_write_value(client, W83781D_REG_RT_IDX, i);
+		w83781d_write_value(client, W83781D_REG_RT_VAL,
+				    data->rt[nr - 1][i]);
+	}
+
+	return count;
+}
+
+#define sysfs_rt(offset) \
+static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \
+{ \
+	return show_rt_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+    return store_rt_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset)
+
+sysfs_rt(1);
+sysfs_rt(2);
+sysfs_rt(3);
+
+#define device_create_file_rt(client, offset) \
+device_create_file(&client->dev, &dev_attr_rt##offset); \
+
+#endif				/* ifdef W83781D_RT */
+
+/* This function is called when:
+     * w83781d_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and w83781d_driver is still present) */
+static int
+w83781d_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	int i = 0, val1 = 0, val2, id;
+	struct i2c_client *new_client;
+	struct w83781d_data *data;
+	int err = 0;
+	const char *type_name = "";
+	const char *client_name = "";
+	int is_isa = i2c_is_isa_adapter(adapter);
+	enum vendor { winbond, asus } vendid;
+
+	if (!is_isa
+	    && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto ERROR0;
+
+	if (is_isa) {
+		if (!request_region(address, W83781D_EXTENT, "w83781d"))
+			goto ERROR0;
+		release_region(address, W83781D_EXTENT);
+	}
+
+	/* Probe whether there is anything available on this address. Already
+	   done for SMBus clients */
+	if (kind < 0) {
+		if (is_isa) {
+
+#define REALLY_SLOW_IO
+			/* We need the timeouts for at least some LM78-like chips. But only
+			   if we read 'undefined' registers. */
+			i = inb_p(address + 1);
+			if (inb_p(address + 2) != i)
+				goto ERROR0;
+			if (inb_p(address + 3) != i)
+				goto ERROR0;
+			if (inb_p(address + 7) != i)
+				goto ERROR0;
+#undef REALLY_SLOW_IO
+
+			/* Let's just hope nothing breaks here */
+			i = inb_p(address + 5) & 0x7f;
+			outb_p(~i & 0x7f, address + 5);
+			if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
+				outb_p(i, address + 5);
+				return 0;
+			}
+		}
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access w83781d_{read,write}_value. */
+
+	if (!(new_client = kmalloc(sizeof (struct i2c_client) +
+				   sizeof (struct w83781d_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+
+	memset(new_client, 0x00, sizeof (struct i2c_client) +
+	       sizeof (struct w83781d_data));
+
+	data = (struct w83781d_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	init_MUTEX(&data->lock);
+	new_client->adapter = adapter;
+	new_client->driver = &w83781d_driver;
+	new_client->flags = 0;
+
+	/* Now, we do the remaining detection. */
+
+	/* The w8378?d may be stuck in some other bank than bank 0. This may
+	   make reading other information impossible. Specify a force=... or
+	   force_*=... parameter, and the Winbond will be reset to the right
+	   bank. */
+	if (kind < 0) {
+		if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80)
+			goto ERROR1;
+		val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
+		val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+		/* Check for Winbond or Asus ID if in bank 0 */
+		if ((!(val1 & 0x07)) &&
+		    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
+		      && (val2 != 0x94))
+		     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
+			 && (val2 != 0x06))))
+			goto ERROR1;
+		/* If Winbond SMBus, check address at 0x48. Asus doesn't support */
+		if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
+				  ((val1 & 0x80) && (val2 == 0x5c)))) {
+			if (w83781d_read_value
+			    (new_client, W83781D_REG_I2C_ADDR) != address)
+				goto ERROR1;
+		}
+	}
+
+	/* We have either had a force parameter, or we have already detected the
+	   Winbond. Put it now into bank 0 and Vendor ID High Byte */
+	w83781d_write_value(new_client, W83781D_REG_BANK,
+			    (w83781d_read_value(new_client,
+						W83781D_REG_BANK) & 0x78) |
+			    0x80);
+
+	/* Determine the chip type. */
+	if (kind <= 0) {
+		/* get vendor ID */
+		val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
+		if (val2 == 0x5c)
+			vendid = winbond;
+		else if ((val2 == 0x12) || (val2 == 0x06))
+			vendid = asus;
+		else
+			goto ERROR1;
+		/* mask off lower bit, not reliable */
+		val1 =
+		    w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
+		if (val1 == 0x10 && vendid == winbond)
+			kind = w83781d;
+		else if (val1 == 0x30 && vendid == winbond)
+			kind = w83782d;
+		else if (val1 == 0x40 && vendid == winbond && !is_isa)
+			kind = w83783s;
+		else if (val1 == 0x20 && vendid == winbond)
+			kind = w83627hf;
+		else if (val1 == 0x30 && vendid == asus && !is_isa)
+			kind = as99127f;
+		else if (val1 == 0x60 && vendid == winbond && is_isa)
+			kind = w83697hf;
+		else {
+			if (kind == 0)
+				dev_warn(&new_client->dev,
+				       "Ignoring 'force' parameter for unknown chip at"
+				       "adapter %d, address 0x%02x\n",
+				       i2c_adapter_id(adapter), address);
+			goto ERROR1;
+		}
+	}
+
+	if (kind == w83781d) {
+		type_name = "w83781d";
+		client_name = "W83781D chip";
+	} else if (kind == w83782d) {
+		type_name = "w83782d";
+		client_name = "W83782D chip";
+	} else if (kind == w83783s) {
+		type_name = "w83783s";
+		client_name = "W83783S chip";
+	} else if (kind == w83627hf) {
+		type_name = "w83627hf";
+		client_name = "W83627HF chip";
+	} else if (kind == as99127f) {
+		type_name = "as99127f";
+		client_name = "AS99127F chip";
+	} else if (kind == w83697hf) {
+		type_name = "w83697hf";
+		client_name = "W83697HF chip";
+	} else {
+		dev_err(&new_client->dev, "Internal error: unknown kind (%d)?!?", kind);
+		goto ERROR1;
+	}
+
+	/* Reserve the ISA region */
+	if (is_isa)
+		request_region(address, W83781D_EXTENT, type_name);
+
+	/* Fill in the remaining client fields and put it into the global list */
+	strncpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
+	data->type = kind;
+
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto ERROR3;
+
+	/* attach secondary i2c lm75-like clients */
+	if (!is_isa) {
+		if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
+					   GFP_KERNEL))) {
+			err = -ENOMEM;
+			goto ERROR4;
+		}
+
+		memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
+
+		id = i2c_adapter_id(adapter);
+		if (force_subclients[0] == id && force_subclients[1] == address) {
+			for (i = 2; i <= 3; i++) {
+				if (force_subclients[i] < 0x48 ||
+				    force_subclients[i] > 0x4f) {
+					dev_err(&new_client->dev,
+					       "Invalid subclient address %d; must be 0x48-0x4f\n",
+					       force_subclients[i]);
+					goto ERROR5;
+				}
+			}
+			w83781d_write_value(new_client,
+					    W83781D_REG_I2C_SUBADDR,
+					    (force_subclients[2] & 0x07) |
+					    ((force_subclients[3] & 0x07) <<
+					     4));
+			data->lm75[0].addr = force_subclients[2];
+		} else {
+			val1 = w83781d_read_value(new_client,
+						  W83781D_REG_I2C_SUBADDR);
+			data->lm75[0].addr = 0x48 + (val1 & 0x07);
+		}
+		if (kind != w83783s) {
+			if (force_subclients[0] == id &&
+			    force_subclients[1] == address) {
+				data->lm75[1].addr = force_subclients[3];
+			} else {
+				data->lm75[1].addr =
+				    0x48 + ((val1 >> 4) & 0x07);
+			}
+			if (data->lm75[0].addr == data->lm75[1].addr) {
+				dev_err(&new_client->dev,
+				       "Duplicate addresses 0x%x for subclients.\n",
+				       data->lm75[0].addr);
+				goto ERROR5;
+			}
+		}
+		if (kind == w83781d)
+			client_name = "W83781D subclient";
+		else if (kind == w83782d)
+			client_name = "W83782D subclient";
+		else if (kind == w83783s)
+			client_name = "W83783S subclient";
+		else if (kind == w83627hf)
+			client_name = "W83627HF subclient";
+		else if (kind == as99127f)
+			client_name = "AS99127F subclient";
+
+		for (i = 0; i <= 1; i++) {
+			i2c_set_clientdata(&data->lm75[i], NULL);	/* store all data in w83781d */
+			data->lm75[i].adapter = adapter;
+			data->lm75[i].driver = &w83781d_driver;
+			data->lm75[i].flags = 0;
+			strncpy(data->lm75[i].dev.name, client_name,
+				DEVICE_NAME_SIZE);
+			if (kind == w83783s)
+				break;
+		}
+	} else {
+		data->lm75 = NULL;
+	}
+
+	device_create_file_in(new_client, 0);
+	if (kind != w83783s && kind != w83697hf)
+		device_create_file_in(new_client, 1);
+	device_create_file_in(new_client, 2);
+	device_create_file_in(new_client, 3);
+	device_create_file_in(new_client, 4);
+	device_create_file_in(new_client, 5);
+	device_create_file_in(new_client, 6);
+	if (kind != as99127f && kind != w83781d && kind != w83783s) {
+		device_create_file_in(new_client, 7);
+		device_create_file_in(new_client, 8);
+	}
+
+	device_create_file_fan(new_client, 1);
+	device_create_file_fan(new_client, 2);
+	if (kind != w83697hf)
+		device_create_file_fan(new_client, 3);
+
+	device_create_file_temp(new_client, 1);
+	device_create_file_temp(new_client, 2);
+	if (kind != w83783s && kind != w83697hf)
+		device_create_file_temp(new_client, 3);
+
+	if (kind != w83697hf)
+		device_create_file_vid(new_client);
+
+	if (kind != w83697hf)
+		device_create_file_vrm(new_client);
+
+	device_create_file_fan_div(new_client, 1);
+	device_create_file_fan_div(new_client, 2);
+	if (kind != w83697hf)
+		device_create_file_fan_div(new_client, 3);
+
+	device_create_file_alarms(new_client);
+
+	device_create_file_beep(new_client);
+
+	if (kind != w83781d) {
+		device_create_file_pwm(new_client, 1);
+		device_create_file_pwm(new_client, 2);
+		device_create_file_pwmenable(new_client, 2);
+	}
+	if (kind == w83782d && !is_isa) {
+		device_create_file_pwm(new_client, 3);
+		device_create_file_pwm(new_client, 4);
+	}
+
+	if (kind != as99127f && kind != w83781d) {
+		device_create_file_sensor(new_client, 1);
+		device_create_file_sensor(new_client, 2);
+		if (kind != w83783s && kind != w83697hf)
+			device_create_file_sensor(new_client, 3);
+	}
+#ifdef W83781D_RT
+	if (kind == w83781d) {
+		device_create_file_rt(new_client, 1);
+		device_create_file_rt(new_client, 2);
+		device_create_file_rt(new_client, 3);
+	}
+#endif
+
+	/* Initialize the chip */
+	w83781d_init_client(new_client);
+	return 0;
+
+/* OK, this is not exactly good programming practice, usually. But it is
+   very code-efficient in this case. */
+
+      ERROR5:
+	if (!is_isa) {
+		i2c_detach_client(&data->lm75[0]);
+		if (data->type != w83783s)
+			i2c_detach_client(&data->lm75[1]);
+		kfree(data->lm75);
+	}
+      ERROR4:
+	i2c_detach_client(new_client);
+      ERROR3:
+	if (is_isa)
+		release_region(address, W83781D_EXTENT);
+      ERROR1:
+	kfree(new_client);
+      ERROR0:
+	return err;
+}
+
+static int
+w83781d_detach_client(struct i2c_client *client)
+{
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev,
+		       "Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
+	if (i2c_is_isa_client(client)) {
+		release_region(client->addr, W83781D_EXTENT);
+	} else {
+		i2c_detach_client(&data->lm75[0]);
+		if (data->type != w83783s)
+			i2c_detach_client(&data->lm75[1]);
+		kfree(data->lm75);
+	}
+	kfree(client);
+
+	return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+   bank switches. ISA access must always be locked explicitly! 
+   We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
+   would slow down the W83781D access and should not be necessary. 
+   There are some ugly typecasts here, but the good news is - they should
+   nowhere else be necessary! */
+static int
+w83781d_read_value(struct i2c_client *client, u16 reg)
+{
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int res, word_sized, bank;
+	struct i2c_client *cl;
+
+	down(&data->lock);
+	if (i2c_is_isa_client(client)) {
+		word_sized = (((reg & 0xff00) == 0x100)
+			      || ((reg & 0xff00) == 0x200))
+		    && (((reg & 0x00ff) == 0x50)
+			|| ((reg & 0x00ff) == 0x53)
+			|| ((reg & 0x00ff) == 0x55));
+		if (reg & 0xff00) {
+			outb_p(W83781D_REG_BANK,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+			outb_p(reg >> 8,
+			       client->addr + W83781D_DATA_REG_OFFSET);
+		}
+		outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
+		res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
+		if (word_sized) {
+			outb_p((reg & 0xff) + 1,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+			res =
+			    (res << 8) + inb_p(client->addr +
+					       W83781D_DATA_REG_OFFSET);
+		}
+		if (reg & 0xff00) {
+			outb_p(W83781D_REG_BANK,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+			outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+		}
+	} else {
+		bank = (reg >> 8) & 0x0f;
+		if (bank > 2)
+			/* switch banks */
+			i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+						  bank);
+		if (bank == 0 || bank > 2) {
+			res = i2c_smbus_read_byte_data(client, reg & 0xff);
+		} else {
+			/* switch to subclient */
+			cl = &data->lm75[bank - 1];
+			/* convert from ISA to LM75 I2C addresses */
+			switch (reg & 0xff) {
+			case 0x50:	/* TEMP */
+				res =
+				    swap_bytes(i2c_smbus_read_word_data(cl, 0));
+				break;
+			case 0x52:	/* CONFIG */
+				res = i2c_smbus_read_byte_data(cl, 1);
+				break;
+			case 0x53:	/* HYST */
+				res =
+				    swap_bytes(i2c_smbus_read_word_data(cl, 2));
+				break;
+			case 0x55:	/* OVER */
+			default:
+				res =
+				    swap_bytes(i2c_smbus_read_word_data(cl, 3));
+				break;
+			}
+		}
+		if (bank > 2)
+			i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+	}
+	up(&data->lock);
+	return res;
+}
+
+static int
+w83781d_write_value(struct i2c_client *client, u16 reg, u16 value)
+{
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int word_sized, bank;
+	struct i2c_client *cl;
+
+	down(&data->lock);
+	if (i2c_is_isa_client(client)) {
+		word_sized = (((reg & 0xff00) == 0x100)
+			      || ((reg & 0xff00) == 0x200))
+		    && (((reg & 0x00ff) == 0x53)
+			|| ((reg & 0x00ff) == 0x55));
+		if (reg & 0xff00) {
+			outb_p(W83781D_REG_BANK,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+			outb_p(reg >> 8,
+			       client->addr + W83781D_DATA_REG_OFFSET);
+		}
+		outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
+		if (word_sized) {
+			outb_p(value >> 8,
+			       client->addr + W83781D_DATA_REG_OFFSET);
+			outb_p((reg & 0xff) + 1,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+		}
+		outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
+		if (reg & 0xff00) {
+			outb_p(W83781D_REG_BANK,
+			       client->addr + W83781D_ADDR_REG_OFFSET);
+			outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
+		}
+	} else {
+		bank = (reg >> 8) & 0x0f;
+		if (bank > 2)
+			/* switch banks */
+			i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
+						  bank);
+		if (bank == 0 || bank > 2) {
+			i2c_smbus_write_byte_data(client, reg & 0xff,
+						  value & 0xff);
+		} else {
+			/* switch to subclient */
+			cl = &data->lm75[bank - 1];
+			/* convert from ISA to LM75 I2C addresses */
+			switch (reg & 0xff) {
+			case 0x52:	/* CONFIG */
+				i2c_smbus_write_byte_data(cl, 1, value & 0xff);
+				break;
+			case 0x53:	/* HYST */
+				i2c_smbus_write_word_data(cl, 2,
+							  swap_bytes(value));
+				break;
+			case 0x55:	/* OVER */
+				i2c_smbus_write_word_data(cl, 3,
+							  swap_bytes(value));
+				break;
+			}
+		}
+		if (bank > 2)
+			i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
+	}
+	up(&data->lock);
+	return 0;
+}
+
+/* Called when we have found a new W83781D. It should set limits, etc. */
+static void
+w83781d_init_client(struct i2c_client *client)
+{
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int vid = 0, i, p;
+	int type = data->type;
+	u8 tmp;
+
+	if (init && type != as99127f) {	/* this resets registers we don't have
+					   documentation for on the as99127f */
+		/* save these registers */
+		i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
+		p = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+		/* Reset all except Watchdog values and last conversion values
+		   This sets fan-divs to 2, among others */
+		w83781d_write_value(client, W83781D_REG_CONFIG, 0x80);
+		/* Restore the registers and disable power-on abnormal beep.
+		   This saves FAN 1/2/3 input/output values set by BIOS. */
+		w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80);
+		w83781d_write_value(client, W83781D_REG_PWMCLK12, p);
+		/* Disable master beep-enable (reset turns it on).
+		   Individual beep_mask should be reset to off but for some reason
+		   disabling this bit helps some people not get beeped */
+		w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
+	}
+
+	if (type != w83697hf) {
+		vid = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x0f;
+		vid |=
+		    (w83781d_read_value(client, W83781D_REG_CHIPID) & 0x01) <<
+		    4;
+		data->vrm = DEFAULT_VRM;
+		vid = vid_from_reg(vid, data->vrm);
+	}
+
+	if ((type != w83781d) && (type != as99127f)) {
+		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
+		for (i = 1; i <= 3; i++) {
+			if (!(tmp & BIT_SCFG1[i - 1])) {
+				data->sens[i - 1] = W83781D_DEFAULT_BETA;
+			} else {
+				if (w83781d_read_value
+				    (client,
+				     W83781D_REG_SCFG2) & BIT_SCFG2[i - 1])
+					data->sens[i - 1] = 1;
+				else
+					data->sens[i - 1] = 2;
+			}
+			if ((type == w83783s || type == w83697hf) && (i == 2))
+				break;
+		}
+	}
+#ifdef W83781D_RT
+/*
+   Fill up the RT Tables.
+   We assume that they are 32 bytes long, in order for temp 1-3.
+   Data sheet documentation is sparse.
+   We also assume that it is only for the 781D although I suspect
+   that the others support it as well....
+*/
+
+	if (init && type == w83781d) {
+		u16 k = 0;
+/*
+    Auto-indexing doesn't seem to work...
+    w83781d_write_value(client,W83781D_REG_RT_IDX,0);
+*/
+		for (i = 0; i < 3; i++) {
+			int j;
+			for (j = 0; j < 32; j++) {
+				w83781d_write_value(client,
+						    W83781D_REG_RT_IDX, k++);
+				data->rt[i][j] =
+				    w83781d_read_value(client,
+						       W83781D_REG_RT_VAL);
+			}
+		}
+	}
+#endif				/* W83781D_RT */
+
+	if (init) {
+		w83781d_write_value(client, W83781D_REG_IN_MIN(0),
+				    IN_TO_REG(W83781D_INIT_IN_MIN_0));
+		w83781d_write_value(client, W83781D_REG_IN_MAX(0),
+				    IN_TO_REG(W83781D_INIT_IN_MAX_0));
+		if (type != w83783s && type != w83697hf) {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(1),
+					    IN_TO_REG(W83781D_INIT_IN_MIN_1));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(1),
+					    IN_TO_REG(W83781D_INIT_IN_MAX_1));
+		}
+
+		w83781d_write_value(client, W83781D_REG_IN_MIN(2),
+				    IN_TO_REG(W83781D_INIT_IN_MIN_2));
+		w83781d_write_value(client, W83781D_REG_IN_MAX(2),
+				    IN_TO_REG(W83781D_INIT_IN_MAX_2));
+		w83781d_write_value(client, W83781D_REG_IN_MIN(3),
+				    IN_TO_REG(W83781D_INIT_IN_MIN_3));
+		w83781d_write_value(client, W83781D_REG_IN_MAX(3),
+				    IN_TO_REG(W83781D_INIT_IN_MAX_3));
+		w83781d_write_value(client, W83781D_REG_IN_MIN(4),
+				    IN_TO_REG(W83781D_INIT_IN_MIN_4));
+		w83781d_write_value(client, W83781D_REG_IN_MAX(4),
+				    IN_TO_REG(W83781D_INIT_IN_MAX_4));
+		if (type == w83781d || type == as99127f) {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(5),
+					    IN_TO_REG(W83781D_INIT_IN_MIN_5));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(5),
+					    IN_TO_REG(W83781D_INIT_IN_MAX_5));
+		} else {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(5),
+					    IN_TO_REG(W83782D_INIT_IN_MIN_5));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(5),
+					    IN_TO_REG(W83782D_INIT_IN_MAX_5));
+		}
+		if (type == w83781d || type == as99127f) {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(6),
+					    IN_TO_REG(W83781D_INIT_IN_MIN_6));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(6),
+					    IN_TO_REG(W83781D_INIT_IN_MAX_6));
+		} else {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(6),
+					    IN_TO_REG(W83782D_INIT_IN_MIN_6));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(6),
+					    IN_TO_REG(W83782D_INIT_IN_MAX_6));
+		}
+		if ((type == w83782d) || (type == w83627hf) ||
+		    (type == w83697hf)) {
+			w83781d_write_value(client, W83781D_REG_IN_MIN(7),
+					    IN_TO_REG(W83781D_INIT_IN_MIN_7));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(7),
+					    IN_TO_REG(W83781D_INIT_IN_MAX_7));
+			w83781d_write_value(client, W83781D_REG_IN_MIN(8),
+					    IN_TO_REG(W83781D_INIT_IN_MIN_8));
+			w83781d_write_value(client, W83781D_REG_IN_MAX(8),
+					    IN_TO_REG(W83781D_INIT_IN_MAX_8));
+			w83781d_write_value(client, W83781D_REG_VBAT,
+					    (w83781d_read_value
+					     (client,
+					      W83781D_REG_VBAT) | 0x01));
+		}
+		w83781d_write_value(client, W83781D_REG_FAN_MIN(1),
+				    FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2));
+		w83781d_write_value(client, W83781D_REG_FAN_MIN(2),
+				    FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2));
+		if (type != w83697hf) {
+			w83781d_write_value(client, W83781D_REG_FAN_MIN(3),
+					    FAN_TO_REG(W83781D_INIT_FAN_MIN_3,
+						       2));
+		}
+
+		w83781d_write_value(client, W83781D_REG_TEMP_OVER(1),
+				    TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
+		w83781d_write_value(client, W83781D_REG_TEMP_HYST(1),
+				    TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
+
+		if (type == as99127f) {
+			w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
+					    AS99127_TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP2_OVER));
+			w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
+					    AS99127_TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP2_HYST));
+		} else {
+			w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
+					    TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP2_OVER));
+			w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
+					    TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP2_HYST));
+		}
+		w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, 0x00);
+
+		if (type == as99127f) {
+			w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
+					    AS99127_TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP3_OVER));
+			w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
+					    AS99127_TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP3_HYST));
+		} else if (type != w83783s && type != w83697hf) {
+			w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
+					    TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP3_OVER));
+			w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
+					    TEMP_ADD_TO_REG
+					    (W83781D_INIT_TEMP3_HYST));
+		}
+		if (type != w83783s && type != w83697hf) {
+			w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
+					    0x00);
+		}
+		if (type != w83781d) {
+			/* enable comparator mode for temp2 and temp3 so
+			   alarm indication will work correctly */
+			w83781d_write_value(client, W83781D_REG_IRQ, 0x41);
+			for (i = 0; i < 3; i++)
+				data->pwmenable[i] = 1;
+		}
+	}
+
+	/* Start monitoring */
+	w83781d_write_value(client, W83781D_REG_CONFIG,
+			    (w83781d_read_value(client,
+						W83781D_REG_CONFIG) & 0xf7)
+			    | 0x01);
+}
+
+static void
+w83781d_update_client(struct i2c_client *client)
+{
+	struct w83781d_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	if (time_after
+	    (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
+	    || time_before(jiffies, data->last_updated) || !data->valid) {
+		pr_debug(KERN_DEBUG "Starting device update\n");
+
+		for (i = 0; i <= 8; i++) {
+			if ((data->type == w83783s || data->type == w83697hf)
+			    && (i == 1))
+				continue;	/* 783S has no in1 */
+			data->in[i] =
+			    w83781d_read_value(client, W83781D_REG_IN(i));
+			data->in_min[i] =
+			    w83781d_read_value(client, W83781D_REG_IN_MIN(i));
+			data->in_max[i] =
+			    w83781d_read_value(client, W83781D_REG_IN_MAX(i));
+			if ((data->type != w83782d) && (data->type != w83697hf)
+			    && (data->type != w83627hf) && (i == 6))
+				break;
+		}
+		for (i = 1; i <= 3; i++) {
+			data->fan[i - 1] =
+			    w83781d_read_value(client, W83781D_REG_FAN(i));
+			data->fan_min[i - 1] =
+			    w83781d_read_value(client, W83781D_REG_FAN_MIN(i));
+		}
+		if (data->type != w83781d) {
+			for (i = 1; i <= 4; i++) {
+				data->pwm[i - 1] =
+				    w83781d_read_value(client,
+						       W83781D_REG_PWM(i));
+				if (((data->type == w83783s)
+				     || (data->type == w83627hf)
+				     || (data->type == as99127f)
+				     || (data->type == w83697hf)
+				     || ((data->type == w83782d)
+					 && i2c_is_isa_client(client)))
+				    && i == 2)
+					break;
+			}
+		}
+
+		data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
+		data->temp_min =
+		    w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
+		data->temp_max =
+		    w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
+		data->temp_add[0] =
+		    w83781d_read_value(client, W83781D_REG_TEMP(2));
+		data->temp_max_add[0] =
+		    w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
+		data->temp_min_add[0] =
+		    w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
+		if (data->type != w83783s && data->type != w83697hf) {
+			data->temp_add[1] =
+			    w83781d_read_value(client, W83781D_REG_TEMP(3));
+			data->temp_max_add[1] =
+			    w83781d_read_value(client,
+					       W83781D_REG_TEMP_OVER(3));
+			data->temp_min_add[1] =
+			    w83781d_read_value(client,
+					       W83781D_REG_TEMP_HYST(3));
+		}
+		i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
+		if (data->type != w83697hf) {
+			data->vid = i & 0x0f;
+			data->vid |=
+			    (w83781d_read_value(client, W83781D_REG_CHIPID) &
+			     0x01)
+			    << 4;
+		}
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = (i >> 6) & 0x03;
+		if (data->type != w83697hf) {
+			data->fan_div[2] = (w83781d_read_value(client,
+							       W83781D_REG_PIN)
+					    >> 6) & 0x03;
+		}
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			i = w83781d_read_value(client, W83781D_REG_VBAT);
+			data->fan_div[0] |= (i >> 3) & 0x04;
+			data->fan_div[1] |= (i >> 4) & 0x04;
+			if (data->type != w83697hf)
+				data->fan_div[2] |= (i >> 5) & 0x04;
+		}
+		data->alarms =
+		    w83781d_read_value(client,
+				       W83781D_REG_ALARM1) +
+		    (w83781d_read_value(client, W83781D_REG_ALARM2) << 8);
+		if ((data->type == w83782d) || (data->type == w83627hf)) {
+			data->alarms |=
+			    w83781d_read_value(client,
+					       W83781D_REG_ALARM3) << 16;
+		}
+		i = w83781d_read_value(client, W83781D_REG_BEEP_INTS2);
+		data->beep_enable = i >> 7;
+		data->beep_mask = ((i & 0x7f) << 8) +
+		    w83781d_read_value(client, W83781D_REG_BEEP_INTS1);
+		if ((data->type != w83781d) && (data->type != as99127f)) {
+			data->beep_mask |=
+			    w83781d_read_value(client,
+					       W83781D_REG_BEEP_INTS3) << 16;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+}
+
+static int __init
+sensors_w83781d_init(void)
+{
+	return i2c_add_driver(&w83781d_driver);
+}
+
+static void __exit
+sensors_w83781d_exit(void)
+{
+	i2c_del_driver(&w83781d_driver);
+}
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+	      "Philip Edelbrock <phil@netroedge.com>, "
+	      "and Mark Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("W83781D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83781d_init);
+module_exit(sensors_w83781d_exit);
diff -urN linux-2.5.66-bk8/drivers/i2c/i2c-core.c linux-2.5.66-bk9/drivers/i2c/i2c-core.c
--- linux-2.5.66-bk8/drivers/i2c/i2c-core.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/i2c-core.c	2003-04-03 04:32:42.000000000 -0800
@@ -29,7 +29,6 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/proc_fs.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
@@ -46,15 +45,6 @@
 /**** debug level */
 static int i2c_debug;
 
-#ifdef CONFIG_PROC_FS
-static int i2cproc_register(struct i2c_adapter *adap, int bus);
-static void i2cproc_remove(int bus);
-#else
-# define i2cproc_register(adap, bus)	0
-# define i2cproc_remove(bus)		do { } while (0)
-#endif /* CONFIG_PROC_FS */
-
-
 int i2c_device_probe(struct device *dev)
 {
 	return -ENODEV;
@@ -98,10 +88,6 @@
 		goto out_unlock;
 	}
 
-	res = i2cproc_register(adap, i);
-	if (res)
-		goto out_unlock;
-
 	adapters[i] = adap;
 
 	init_MUTEX(&adap->bus);
@@ -180,8 +166,6 @@
 		}
 	}
 
-	i2cproc_remove(i);
-
 	/* clean up the sysfs representation */
 	device_unregister(&adap->dev);
 
@@ -392,7 +376,8 @@
 	client->dev.driver = &client->driver->driver;
 	client->dev.bus = &i2c_bus_type;
 	
-	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), "i2c_dev_%d", i);
+	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
+		"%d-%04x", i2c_adapter_id(adapter), client->addr);
 	printk("registering %s\n", client->dev.bus_id);
 	device_register(&client->dev);
 	
@@ -494,173 +479,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-/* This function generates the output for /proc/bus/i2c-? */
-static ssize_t i2cproc_bus_read(struct file *file, char *buf,
-				size_t count, loff_t *ppos)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	char *kbuf;
-	struct i2c_client *client;
-	int i,j,k,order_nr,len=0;
-	size_t len_total;
-	int order[I2C_CLIENT_MAX];
-#define OUTPUT_LENGTH_PER_LINE 70
-
-	len_total = file->f_pos + count;
-	if (len_total > (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE) )
-		/* adjust to maximum file size */
-		len_total = (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE);
-	for (i = 0; i < I2C_ADAP_MAX; i++)
-		if (adapters[i]->inode == inode->i_ino) {
-		/* We need a bit of slack in the kernel buffer; this makes the
-		   sprintf safe. */
-			if (! (kbuf = kmalloc(len_total +
-			                      OUTPUT_LENGTH_PER_LINE,
-			                      GFP_KERNEL)))
-				return -ENOMEM;
-			/* Order will hold the indexes of the clients
-			   sorted by address */
-			order_nr=0;
-			for (j = 0; j < I2C_CLIENT_MAX; j++) {
-				if ((client = adapters[i]->clients[j]) && 
-				    (client->driver->id != I2C_DRIVERID_I2CDEV))  {
-					for(k = order_nr; 
-					    (k > 0) && 
-					    adapters[i]->clients[order[k-1]]->
-					             addr > client->addr; 
-					    k--)
-						order[k] = order[k-1];
-					order[k] = j;
-					order_nr++;
-				}
-			}
-
-
-			for (j = 0; (j < order_nr) && (len < len_total); j++) {
-				client = adapters[i]->clients[order[j]];
-				len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
-				              client->addr,
-				              client->dev.name,
-				              client->driver->name);
-			}
-			len = len - file->f_pos;
-			if (len > count)
-				len = count;
-			if (len < 0) 
-				len = 0;
-			if (copy_to_user (buf,kbuf+file->f_pos, len)) {
-				kfree(kbuf);
-				return -EFAULT;
-			}
-			file->f_pos += len;
-			kfree(kbuf);
-			return len;
-		}
-	return -ENOENT;
-}
-
-static struct file_operations i2cproc_operations = {
-	.read		= i2cproc_bus_read,
-};
-
-/* This function generates the output for /proc/bus/i2c */
-static int bus_i2c_show(struct seq_file *s, void *p)
-{
-	int i;
-
-	down(&core_lists);
-	for (i = 0; i < I2C_ADAP_MAX; i++) {
-		struct i2c_adapter *adapter = adapters[i];
-
-		if (!adapter)
-			continue;
-
-		seq_printf(s, "i2c-%d\t", i);
-
-		if (adapter->algo->smbus_xfer) {
-			if (adapter->algo->master_xfer)
-				seq_printf(s, "smbus/i2c");
-			else
-				seq_printf(s, "smbus    ");
-		} else if (adapter->algo->master_xfer)
-			seq_printf(s ,"i2c       ");
-		else
-			seq_printf(s, "dummy     ");
-
-		seq_printf(s, "\t%-32s\t%-32s\n",
-			      adapter->dev.name, adapter->algo->name);
-	}
-	up(&core_lists);
-
-	return 0;
-}
-
-static int bus_i2c_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, bus_i2c_show, NULL);
-}
-
-static struct file_operations bus_i2c_fops = {
-	.open		= bus_i2c_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
- };
-
-static int i2cproc_register(struct i2c_adapter *adap, int bus)
-{
-	struct proc_dir_entry *proc_entry;
-	char name[8];
-
-	sprintf(name, "i2c-%d", bus);
-
-	proc_entry = create_proc_entry(name, 0, proc_bus);
-	if (!proc_entry)
-		goto fail;
-
-	proc_entry->proc_fops = &i2cproc_operations;
-	proc_entry->owner = adap->owner;
-	adap->inode = proc_entry->low_ino;
-	return 0;
- fail:
-	printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name);
-	return -ENOENT;
-}
-
-static void i2cproc_remove(int bus)
-{
-	char name[8];
-
-	sprintf(name,"i2c-%d", bus);
-	remove_proc_entry(name, proc_bus);
-}
-
-static int __init i2cproc_init(void)
-{
-	struct proc_dir_entry *proc_bus_i2c;
-
-	proc_bus_i2c = create_proc_entry("i2c", 0, proc_bus);
-	if (!proc_bus_i2c)
-		goto fail;
-	proc_bus_i2c->proc_fops = &bus_i2c_fops;
- 	proc_bus_i2c->owner = THIS_MODULE;
- 	return 0;
-
- fail:
-	printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
-	return -ENOENT;
-}
-
-static void __exit i2cproc_cleanup(void)
-{
-	remove_proc_entry("i2c",proc_bus);
-}
-#else
-static int __init i2cproc_init(void) { return 0; }
-static void __exit i2cproc_cleanup(void) { }
-#endif /* CONFIG_PROC_FS */
-
 /* match always succeeds, as we want the probe() to tell if we really accept this match */
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
@@ -675,13 +493,11 @@
 
 static int __init i2c_init(void)
 {
-	bus_register(&i2c_bus_type);
-	return i2cproc_init();
+	return bus_register(&i2c_bus_type);
 }
 
 static void __exit i2c_exit(void)
 {
-	i2cproc_cleanup();
 	bus_unregister(&i2c_bus_type);
 }
 
diff -urN linux-2.5.66-bk8/drivers/i2c/i2c-proc.c linux-2.5.66-bk9/drivers/i2c/i2c-proc.c
--- linux-2.5.66-bk8/drivers/i2c/i2c-proc.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/i2c-proc.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,733 +0,0 @@
-/*
-    i2c-proc.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.
-*/
-
-/*
-    This driver puts entries in /proc/sys/dev/sensors for each I2C device
-*/
-
-/* #define DEBUG 1 */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/i2c.h>
-#include <linux/i2c-proc.h>
-#include <asm/uaccess.h>
-
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
-			       long *results, int magnitude);
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
-			       long *results, int magnitude);
-static int i2c_proc_chips(ctl_table * ctl, int write,
-			      struct file *filp, void *buffer,
-			      size_t * lenp);
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
-				void *oldval, size_t * oldlenp,
-				void *newval, size_t newlen,
-				void **context);
-
-#define SENSORS_ENTRY_MAX 20
-static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
-
-static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
-
-static ctl_table i2c_proc_dev_sensors[] = {
-	{SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips,
-	 &i2c_sysctl_chips},
-	{0}
-};
-
-static ctl_table i2c_proc_dev[] = {
-	{DEV_SENSORS, "sensors", NULL, 0, 0555, i2c_proc_dev_sensors},
-	{0},
-};
-
-
-static ctl_table i2c_proc[] = {
-	{CTL_DEV, "dev", NULL, 0, 0555, i2c_proc_dev},
-	{0}
-};
-
-
-static struct ctl_table_header *i2c_proc_header;
-
-/* This returns a nice name for a new directory; for example lm78-isa-0310
-   (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
-   a LM75 chip on the third i2c bus at address 0x4e).  
-   name is allocated first. */
-static char *generate_name(struct i2c_client *client, const char *prefix)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int addr = client->addr;
-	char name_buffer[50], *name;
-
-	if (i2c_is_isa_adapter(adapter)) {
-		sprintf(name_buffer, "%s-isa-%04x", prefix, addr);
-	} else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) {
-		int id = i2c_adapter_id(adapter);
-		if (id < 0)
-			return ERR_PTR(-ENOENT);
-		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
-	} else {	/* dummy adapter, generate prefix */
-		int end, i;
-
-		sprintf(name_buffer, "%s-", prefix);
-		end = strlen(name_buffer);
-
-		for (i = 0; i < 32; i++) {
-			if (adapter->algo->name[i] == ' ')
-				break;
-			name_buffer[end++] = tolower(adapter->algo->name[i]);
-		}
-
-		name_buffer[end] = 0;
-		sprintf(name_buffer + end, "-%04x", addr);
-	}
-
-	name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
-	if (unlikely(!name))
-		return ERR_PTR(-ENOMEM);
-	strcpy(name, name_buffer);
-	return name;
-}
-
-/* This rather complex function must be called when you want to add an entry
-   to /proc/sys/dev/sensors/chips. It also creates a new directory within 
-   /proc/sys/dev/sensors/.
-   ctl_template should be a template of the newly created directory. It is
-   copied in memory. The extra2 field of each file is set to point to client.
-   If any driver wants subdirectories within the newly created directory,
-   this function must be updated!  */
-int i2c_register_entry(struct i2c_client *client, const char *prefix,
-		       struct ctl_table *leaf)
-{
-	struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl;
-	struct ctl_table_header *hdr;
-	struct ctl_table *tmp;
-	const char *name;
-	int id;
-
-	name = generate_name(client, prefix);
-	if (IS_ERR(name))
-		return PTR_ERR(name);
-
-	for (id = 0; id < SENSORS_ENTRY_MAX; id++) {
-		if (!i2c_entries[id])
-			goto free_slot;
-	}
-
-	goto out_free_name;
-
- free_slot:
-	tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
-	if (unlikely(!tbl))
-		goto out_free_name;
-	memset(tbl, 0, sizeof(*tbl));
-
-	for (tmp = leaf; tmp->ctl_name; tmp++)
-		tmp->extra2 = client;
-
-	tbl->sensors->ctl_name = id+256;
-	tbl->sensors->procname = name;
-	tbl->sensors->mode = 0555;
-	tbl->sensors->child = leaf;
-
-	tbl->dev->ctl_name = DEV_SENSORS;
-	tbl->dev->procname = "sensors";
-	tbl->dev->mode = 0555;
-	tbl->dev->child = tbl->sensors;
-
-	tbl->root->ctl_name = CTL_DEV;
-	tbl->root->procname = "dev";
-	tbl->root->mode = 0555;
-	tbl->root->child = tbl->dev;
-
-	hdr = register_sysctl_table(tbl->root, 0);
-	if (unlikely(!hdr))
-		goto out_free_tbl;
-
-	i2c_entries[id] = hdr;
-	i2c_clients[id] = client;
-
-	return (id + 256);	/* XXX(hch) why?? */
-
- out_free_tbl:
-	kfree(tbl);
- out_free_name:
-	kfree(name);
-	return -ENOMEM;
-}
-
-void i2c_deregister_entry(int id)
-{
-	id -= 256;
-
-	if (i2c_entries[id]) {
-		struct ctl_table_header *hdr = i2c_entries[id];
-		struct ctl_table *tbl = hdr->ctl_table;
-
-		unregister_sysctl_table(hdr);
-		kfree(tbl->child->child->procname);
-		kfree(tbl); /* actually the whole anonymous struct */
-	}
-
-	i2c_entries[id] = NULL;
-	i2c_clients[id] = NULL;
-}
-
-static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
-		       void *buffer, size_t * lenp)
-{
-	char BUF[SENSORS_PREFIX_MAX + 30];
-	int buflen, curbufsize, i;
-	struct ctl_table *client_tbl;
-
-	if (write)
-		return 0;
-
-	/* If buffer is size 0, or we try to read when not at the start, we
-	   return nothing. Note that I think writing when not at the start
-	   does not work either, but anyway, this is straight from the kernel
-	   sources. */
-	if (!*lenp || (filp->f_pos && !write)) {
-		*lenp = 0;
-		return 0;
-	}
-	curbufsize = 0;
-	for (i = 0; i < SENSORS_ENTRY_MAX; i++)
-		if (i2c_entries[i]) {
-			client_tbl =
-			    i2c_entries[i]->ctl_table->child->child;
-			buflen =
-			    sprintf(BUF, "%d\t%s\n", client_tbl->ctl_name,
-				    client_tbl->procname);
-			if (buflen + curbufsize > *lenp)
-				buflen = *lenp - curbufsize;
-			if(copy_to_user(buffer, BUF, buflen))
-				return -EFAULT;
-			curbufsize += buflen;
-			(char *) buffer += buflen;
-		}
-	*lenp = curbufsize;
-	filp->f_pos += curbufsize;
-	return 0;
-}
-
-static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
-			 void *oldval, size_t * oldlenp, void *newval,
-			 size_t newlen, void **context)
-{
-	struct i2c_chips_data data;
-	int i, oldlen, nrels, maxels,ret=0;
-	struct ctl_table *client_tbl;
-
-	if (oldval && oldlenp && !((ret = get_user(oldlen, oldlenp))) && 
-	    oldlen) {
-		maxels = oldlen / sizeof(struct i2c_chips_data);
-		nrels = 0;
-		for (i = 0; (i < SENSORS_ENTRY_MAX) && (nrels < maxels);
-		     i++)
-			if (i2c_entries[i]) {
-				client_tbl =
-				    i2c_entries[i]->ctl_table->child->
-				    child;
-				data.sysctl_id = client_tbl->ctl_name;
-				strcpy(data.name, client_tbl->procname);
-				if(copy_to_user(oldval, &data,
-					     sizeof(struct
-						    i2c_chips_data)))
-					return -EFAULT;
-				(char *) oldval +=
-				    sizeof(struct i2c_chips_data);
-				nrels++;
-			}
-		oldlen = nrels * sizeof(struct i2c_chips_data);
-		if(put_user(oldlen, oldlenp))
-			return -EFAULT;
-	}
-	return ret;
-}
-
-
-/* This function reads or writes a 'real' value (encoded by the combination
-   of an integer and a magnitude, the last is the power of ten the value
-   should be divided with) to a /proc/sys directory. To use this function,
-   you must (before registering the ctl_table) set the extra2 field to the
-   client, and the extra1 field to a function of the form:
-      void func(struct i2c_client *client, int operation, int ctl_name,
-                int *nrels_mag, long *results)
-   This function can be called for three values of operation. If operation
-   equals SENSORS_PROC_REAL_INFO, the magnitude should be returned in 
-   nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
-   be read into results. nrels_mag should return the number of elements
-   read; the maximum number is put in it on entry. Finally, if operation
-   equals SENSORS_PROC_REAL_WRITE, the values in results should be
-   written to the chip. nrels_mag contains on entry the number of elements
-   found.
-   In all cases, client points to the client we wish to interact with,
-   and ctl_name is the SYSCTL id of the file we are accessing. */
-int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
-		      void *buffer, size_t * lenp)
-{
-#define MAX_RESULTS 32
-	int mag, nrels = MAX_RESULTS;
-	long results[MAX_RESULTS];
-	i2c_real_callback callback = ctl->extra1;
-	struct i2c_client *client = ctl->extra2;
-	int res;
-
-	/* If buffer is size 0, or we try to read when not at the start, we
-	   return nothing. Note that I think writing when not at the start
-	   does not work either, but anyway, this is straight from the kernel
-	   sources. */
-	if (!*lenp || (filp->f_pos && !write)) {
-		*lenp = 0;
-		return 0;
-	}
-
-	/* Get the magnitude */
-	callback(client, SENSORS_PROC_REAL_INFO, ctl->ctl_name, &mag,
-		 NULL);
-
-	if (write) {
-		/* Read the complete input into results, converting to longs */
-		res = i2c_parse_reals(&nrels, buffer, *lenp, results, mag);
-		if (res)
-			return res;
-
-		if (!nrels)
-			return 0;
-
-		/* Now feed this information back to the client */
-		callback(client, SENSORS_PROC_REAL_WRITE, ctl->ctl_name,
-			 &nrels, results);
-
-		filp->f_pos += *lenp;
-		return 0;
-	} else {		/* read */
-		/* Get the information from the client into results */
-		callback(client, SENSORS_PROC_REAL_READ, ctl->ctl_name,
-			 &nrels, results);
-
-		/* And write them to buffer, converting to reals */
-		res = i2c_write_reals(nrels, buffer, lenp, results, mag);
-		if (res)
-			return res;
-		filp->f_pos += *lenp;
-		return 0;
-	}
-}
-
-/* This function is equivalent to i2c_proc_real, only it interacts with
-   the sysctl(2) syscall, and returns no reals, but integers */
-int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
-			void *oldval, size_t * oldlenp, void *newval,
-			size_t newlen, void **context)
-{
-	long results[MAX_RESULTS];
-	int oldlen, nrels = MAX_RESULTS,ret=0;
-	i2c_real_callback callback = table->extra1;
-	struct i2c_client *client = table->extra2;
-
-	/* Check if we need to output the old values */
-	if (oldval && oldlenp && !((ret=get_user(oldlen, oldlenp))) && oldlen) {
-		callback(client, SENSORS_PROC_REAL_READ, table->ctl_name,
-			 &nrels, results);
-
-		/* Note the rounding factor! */
-		if (nrels * sizeof(long) < oldlen)
-			oldlen = nrels * sizeof(long);
-		oldlen = (oldlen / sizeof(long)) * sizeof(long);
-		if(copy_to_user(oldval, results, oldlen))
-			return -EFAULT;
-		if(put_user(oldlen, oldlenp))
-			return -EFAULT;
-	}
-
-	if (newval && newlen) {
-		/* Note the rounding factor! */
-		newlen -= newlen % sizeof(long);
-		nrels = newlen / sizeof(long);
-		if(copy_from_user(results, newval, newlen))
-			return -EFAULT;
-
-		/* Get the new values back to the client */
-		callback(client, SENSORS_PROC_REAL_WRITE, table->ctl_name,
-			 &nrels, results);
-	}
-	return ret;
-}
-
-
-/* nrels contains initially the maximum number of elements which can be
-   put in results, and finally the number of elements actually put there.
-   A magnitude of 1 will multiply everything with 10; etc.
-   buffer, bufsize is the character buffer we read from and its length.
-   results will finally contain the parsed integers. 
-
-   Buffer should contain several reals, separated by whitespace. A real
-   has the following syntax:
-     [ Minus ] Digit* [ Dot Digit* ] 
-   (everything between [] is optional; * means zero or more).
-   When the next character is unparsable, everything is skipped until the
-   next whitespace.
-
-   WARNING! This is tricky code. I have tested it, but there may still be
-            hidden bugs in it, even leading to crashes and things!
-*/
-static int i2c_parse_reals(int *nrels, void *buffer, int bufsize,
-			 long *results, int magnitude)
-{
-	int maxels, min, mag;
-	long res,ret=0;
-	char nextchar = 0;
-
-	maxels = *nrels;
-	*nrels = 0;
-
-	while (bufsize && (*nrels < maxels)) {
-
-		/* Skip spaces at the start */
-		while (bufsize && 
-		       !((ret=get_user(nextchar, (char *) buffer))) &&
-		       isspace((int) nextchar)) {
-			bufsize--;
-			((char *) buffer)++;
-		}
-
-		if (ret)
-			return -EFAULT;	
-		/* Well, we may be done now */
-		if (!bufsize)
-			return 0;
-
-		/* New defaults for our result */
-		min = 0;
-		res = 0;
-		mag = magnitude;
-
-		/* Check for a minus */
-		if (!((ret=get_user(nextchar, (char *) buffer)))
-		    && (nextchar == '-')) {
-			min = 1;
-			bufsize--;
-			((char *) buffer)++;
-		}
-		if (ret)
-			return -EFAULT;
-
-		/* Digits before a decimal dot */
-		while (bufsize && 
-		       !((ret=get_user(nextchar, (char *) buffer))) &&
-		       isdigit((int) nextchar)) {
-			res = res * 10 + nextchar - '0';
-			bufsize--;
-			((char *) buffer)++;
-		}
-		if (ret)
-			return -EFAULT;
-
-		/* If mag < 0, we must actually divide here! */
-		while (mag < 0) {
-			res = res / 10;
-			mag++;
-		}
-
-		if (bufsize && (nextchar == '.')) {
-			/* Skip the dot */
-			bufsize--;
-			((char *) buffer)++;
-
-			/* Read digits while they are significant */
-			while (bufsize && (mag > 0) &&
-			       !((ret=get_user(nextchar, (char *) buffer))) &&
-			       isdigit((int) nextchar)) {
-				res = res * 10 + nextchar - '0';
-				mag--;
-				bufsize--;
-				((char *) buffer)++;
-			}
-			if (ret)
-				return -EFAULT;
-		}
-		/* If we are out of data, but mag > 0, we need to scale here */
-		while (mag > 0) {
-			res = res * 10;
-			mag--;
-		}
-
-		/* Skip everything until we hit whitespace */
-		while (bufsize && 
-		       !((ret=get_user(nextchar, (char *) buffer))) &&
-		       isspace((int) nextchar)) {
-			bufsize--;
-			((char *) buffer)++;
-		}
-		if (ret)
-			return -EFAULT;
-
-		/* Put res in results */
-		results[*nrels] = (min ? -1 : 1) * res;
-		(*nrels)++;
-	}
-
-	/* Well, there may be more in the buffer, but we need no more data. 
-	   Ignore anything that is left. */
-	return 0;
-}
-
-static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize,
-			 long *results, int magnitude)
-{
-#define BUFLEN 20
-	char BUF[BUFLEN + 1];	/* An individual representation should fit! */
-	char printfstr[10];
-	int nr = 0;
-	int buflen, mag, times;
-	int curbufsize = 0;
-
-	while ((nr < nrels) && (curbufsize < *bufsize)) {
-		mag = magnitude;
-
-		if (nr != 0) {
-			if(put_user(' ', (char *) buffer))
-				return -EFAULT;
-			curbufsize++;
-			((char *) buffer)++;
-		}
-
-		/* Fill BUF with the representation of the next string */
-		if (mag <= 0) {
-			buflen = sprintf(BUF, "%ld", results[nr]);
-			if (buflen < 0) {	/* Oops, a sprintf error! */
-				*bufsize = 0;
-				return -EINVAL;
-			}
-			while ((mag < 0) && (buflen < BUFLEN)) {
-				BUF[buflen++] = '0';
-				mag++;
-			}
-			BUF[buflen] = 0;
-		} else {
-			times = 1;
-			for (times = 1; mag-- > 0; times *= 10);
-			if (results[nr] < 0) {
-				BUF[0] = '-';
-				buflen = 1;
-			} else
-				buflen = 0;
-			strcpy(printfstr, "%ld.%0Xld");
-			printfstr[6] = magnitude + '0';
-			buflen +=
-			    sprintf(BUF + buflen, printfstr,
-				    abs(results[nr]) / times,
-				    abs(results[nr]) % times);
-			if (buflen < 0) {	/* Oops, a sprintf error! */
-				*bufsize = 0;
-				return -EINVAL;
-			}
-		}
-
-		/* Now copy it to the user-space buffer */
-		if (buflen + curbufsize > *bufsize)
-			buflen = *bufsize - curbufsize;
-		if(copy_to_user(buffer, BUF, buflen))
-			return -EFAULT;
-		curbufsize += buflen;
-		(char *) buffer += buflen;
-
-		nr++;
-	}
-	if (curbufsize < *bufsize) {
-		if(put_user('\n', (char *) buffer))
-			return -EFAULT;
-		curbufsize++;
-	}
-	*bufsize = curbufsize;
-	return 0;
-}
-
-
-/* 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,
-		   i2c_found_addr_proc * found_proc)
-{
-	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 ? SENSORS_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++) {
-		/* XXX: WTF is going on here??? */
-		if ((is_isa && check_region(addr, 1)) ||
-		    (!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] != SENSORS_I2C_END); j += 2) {
-				if ( ((adapter_id == this_force->force[j]) ||
-				      ((this_force->force[j] == SENSORS_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, 0, 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] != SENSORS_I2C_END); i += 2) {
-			if ( ((adapter_id == address_data->ignore[i]) ||
-			      ((address_data->ignore[i] == SENSORS_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] != SENSORS_I2C_END); i += 3) {
-			if ( ((adapter_id == address_data->ignore_range[i]) ||
-			      ((address_data-> ignore_range[i] == SENSORS_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] != SENSORS_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] != SENSORS_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] != SENSORS_I2C_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] != SENSORS_I2C_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] != SENSORS_I2C_END);
-		     i += 2) {
-			if (((adapter_id == address_data->probe[i]) ||
-			     ((address_data->
-			       probe[i] == SENSORS_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] != SENSORS_I2C_END); i += 3) {
-			if ( ((adapter_id == address_data->probe_range[i]) ||
-			      ((address_data->probe_range[i] == SENSORS_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, 0, -1)))
-				return err;
-	}
-	return 0;
-}
-
-static int __init i2c_proc_init(void)
-{
-	printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
-	if (!
-	    (i2c_proc_header =
-	     register_sysctl_table(i2c_proc, 0))) {
-		printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
-		return -EPERM;
-	}
-	i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
-	return 0;
-}
-
-static void __exit i2c_proc_exit(void)
-{
-	unregister_sysctl_table(i2c_proc_header);
-}
-
-EXPORT_SYMBOL(i2c_register_entry);
-EXPORT_SYMBOL(i2c_deregister_entry);
-EXPORT_SYMBOL(i2c_proc_real);
-EXPORT_SYMBOL(i2c_sysctl_real);
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("i2c-proc driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_proc_init);
-module_exit(i2c_proc_exit);
diff -urN linux-2.5.66-bk8/drivers/i2c/i2c-sensor.c linux-2.5.66-bk9/drivers/i2c/i2c-sensor.c
--- linux-2.5.66-bk8/drivers/i2c/i2c-sensor.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/drivers/i2c/i2c-sensor.c	2003-04-03 04:32:42.000000000 -0800
@@ -0,0 +1,182 @@
+/*
+    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.
+*/
+
+/* #define DEBUG 1 */
+
+#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,
+		   i2c_found_addr_proc * found_proc)
+{
+	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 ? SENSORS_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++) {
+		/* XXX: WTF is going on here??? */
+		if ((is_isa && check_region(addr, 1)) ||
+		    (!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] != SENSORS_I2C_END); j += 2) {
+				if ( ((adapter_id == this_force->force[j]) ||
+				      ((this_force->force[j] == SENSORS_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] != SENSORS_I2C_END); i += 2) {
+			if ( ((adapter_id == address_data->ignore[i]) ||
+			      ((address_data->ignore[i] == SENSORS_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] != SENSORS_I2C_END); i += 3) {
+			if ( ((adapter_id == address_data->ignore_range[i]) ||
+			      ((address_data-> ignore_range[i] == SENSORS_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] != SENSORS_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] != SENSORS_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] != SENSORS_I2C_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] != SENSORS_I2C_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] != SENSORS_I2C_END);
+		     i += 2) {
+			if (((adapter_id == address_data->probe[i]) ||
+			     ((address_data->
+			       probe[i] == SENSORS_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] != SENSORS_I2C_END); i += 3) {
+			if ( ((adapter_id == address_data->probe_range[i]) ||
+			      ((address_data->probe_range[i] == SENSORS_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;
+}
+
+static int __init i2c_sensor_init(void)
+{
+	return 0;
+}
+
+static void __exit i2c_sensor_exit(void)
+{
+}
+
+EXPORT_SYMBOL(i2c_detect);
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_DESCRIPTION("i2c-sensor driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_sensor_init);
+module_exit(i2c_sensor_exit);
diff -urN linux-2.5.66-bk8/drivers/media/video/adv7175.c linux-2.5.66-bk9/drivers/media/video/adv7175.c
--- linux-2.5.66-bk8/drivers/media/video/adv7175.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/drivers/media/video/adv7175.c	2003-04-03 04:32:42.000000000 -0800
@@ -231,7 +231,7 @@
 static int adv717x_detach(struct i2c_client *client)
 {
 	i2c_detach_client(client);
-	i2c_get_clientdata(client);
+	kfree(i2c_get_clientdata(client));
 	kfree(client);
 	return 0;
 }
diff -urN linux-2.5.66-bk8/drivers/media/video/tvmixer.c linux-2.5.66-bk9/drivers/media/video/tvmixer.c
--- linux-2.5.66-bk8/drivers/media/video/tvmixer.c	2003-03-24 14:01:24.000000000 -0800
+++ linux-2.5.66-bk9/drivers/media/video/tvmixer.c	2003-04-03 04:32:42.000000000 -0800
@@ -87,7 +87,7 @@
         if (cmd == SOUND_MIXER_INFO) {
                 mixer_info info;
                 strncpy(info.id, "tv card", sizeof(info.id));
-                strncpy(info.name, client->name, sizeof(info.name));
+                strncpy(info.name, client->dev.name, sizeof(info.name));
                 info.modify_counter = 42 /* FIXME */;
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
@@ -96,7 +96,7 @@
         if (cmd == SOUND_OLD_MIXER_INFO) {
                 _old_mixer_info info;
                 strncpy(info.id, "tv card", sizeof(info.id));
-                strncpy(info.name, client->name, sizeof(info.name));
+                strncpy(info.name, client->dev.name, sizeof(info.name));
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
                 return 0;
@@ -237,7 +237,7 @@
 	int i;
 
 	if (debug)
-		printk("tvmixer: adapter %s\n",adap->name);
+		printk("tvmixer: adapter %s\n",adap->dev.name);
 	for (i=0; i<I2C_CLIENT_MAX; i++) {
 		if (!adap->clients[i])
 			continue;
@@ -261,10 +261,10 @@
 		/* ignore that one */
 		if (debug)
 			printk("tvmixer: %s is not a tv card\n",
-			       client->adapter->name);
+			       client->adapter->dev.name);
 		return -1;
 	}
-	printk("tvmixer: debug: %s\n",client->name);
+	printk("tvmixer: debug: %s\n",client->dev.name);
 
 	/* unregister ?? */
 	for (i = 0; i < DEV_MAX; i++) {
@@ -273,7 +273,7 @@
 			unregister_sound_mixer(devices[i].minor);
 			devices[i].dev = NULL;
 			devices[i].minor = -1;
-			printk("tvmixer: %s unregistered (#1)\n",client->name);
+			printk("tvmixer: %s unregistered (#1)\n",client->dev.name);
 			return 0;
 		}
 	}
@@ -298,13 +298,13 @@
 	if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) {
 		if (debug)
 			printk("tvmixer: %s: VIDIOCGAUDIO failed\n",
-			       client->name);
+			       client->dev.name);
 		return -1;
 	}
 	if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) {
 		if (debug)
 			printk("tvmixer: %s: has no volume control\n",
-			       client->name);
+			       client->dev.name);
 		return -1;
 	}
 
@@ -318,7 +318,7 @@
 	devices[i].count = 0;
 	devices[i].dev   = client;
 	printk("tvmixer: %s (%s) registered with minor %d\n",
-	       client->name,client->adapter->name,minor);
+	       client->dev.name,client->adapter->dev.name,minor);
 	
 	return 0;
 }
@@ -344,7 +344,7 @@
 		if (devices[i].minor != -1) {
 			unregister_sound_mixer(devices[i].minor);
 			printk("tvmixer: %s unregistered (#2)\n",
-			       devices[i].dev->name);
+			       devices[i].dev->dev.name);
 		}
 	}
 }
diff -urN linux-2.5.66-bk8/drivers/usb/serial/generic.c linux-2.5.66-bk9/drivers/usb/serial/generic.c
--- linux-2.5.66-bk8/drivers/usb/serial/generic.c	2003-03-24 14:00:00.000000000 -0800
+++ linux-2.5.66-bk9/drivers/usb/serial/generic.c	2003-04-03 04:32:42.000000000 -0800
@@ -17,6 +17,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
 	static int debug = 1;
diff -urN linux-2.5.66-bk8/include/asm-i386/apic.h linux-2.5.66-bk9/include/asm-i386/apic.h
--- linux-2.5.66-bk8/include/asm-i386/apic.h	2003-03-24 14:01:48.000000000 -0800
+++ linux-2.5.66-bk9/include/asm-i386/apic.h	2003-04-03 04:32:42.000000000 -0800
@@ -79,13 +79,16 @@
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern void setup_apic_nmi_watchdog (void);
+extern void disable_lapic_nmi_watchdog(void);
+extern void enable_lapic_nmi_watchdog(void);
 extern inline void nmi_watchdog_tick (struct pt_regs * regs);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 
-extern struct pm_dev *apic_pm_register(pm_dev_t, unsigned long, pm_callback);
-extern void apic_pm_unregister(struct pm_dev*);
+#ifdef CONFIG_PM
+extern struct sys_device device_lapic;
+#endif
 
 extern int check_nmi_watchdog (void);
 extern void enable_NMI_through_LVT0 (void * dummy);
diff -urN linux-2.5.66-bk8/include/asm-i386/nmi.h linux-2.5.66-bk9/include/asm-i386/nmi.h
--- linux-2.5.66-bk8/include/asm-i386/nmi.h	2003-03-24 14:00:15.000000000 -0800
+++ linux-2.5.66-bk9/include/asm-i386/nmi.h	2003-04-03 04:32:42.000000000 -0800
@@ -25,25 +25,4 @@
  */
 void unset_nmi_callback(void);
  
-#ifdef CONFIG_PM
- 
-/** Replace the PM callback routine for NMI. */
-struct pm_dev * set_nmi_pm_callback(pm_callback callback);
-
-/** Unset the PM callback routine back to the default. */
-void unset_nmi_pm_callback(struct pm_dev * dev);
-
-#else
-
-static inline struct pm_dev * set_nmi_pm_callback(pm_callback callback)
-{
-	return 0;
-} 
- 
-static inline void unset_nmi_pm_callback(struct pm_dev * dev)
-{
-}
-
-#endif /* CONFIG_PM */
- 
 #endif /* ASM_NMI_H */
diff -urN linux-2.5.66-bk8/include/linux/i2c-proc.h linux-2.5.66-bk9/include/linux/i2c-proc.h
--- linux-2.5.66-bk8/include/linux/i2c-proc.h	2003-03-24 14:00:48.000000000 -0800
+++ linux-2.5.66-bk9/include/linux/i2c-proc.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,414 +0,0 @@
-/*
-    i2c-proc.h - Part of the i2c package
-    was originally sensors.h - Part of lm_sensors, Linux kernel modules
-                               for hardware monitoring
-    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _LINUX_I2C_PROC_H
-#define _LINUX_I2C_PROC_H
-
-#include <linux/sysctl.h>
-
-/* The type of callback functions used in sensors_{proc,sysctl}_real */
-typedef void (*i2c_real_callback) (struct i2c_client * client,
-				       int operation, int ctl_name,
-				       int *nrels_mag, long *results);
-
-/* Values for the operation field in the above function type */
-#define SENSORS_PROC_REAL_INFO 1
-#define SENSORS_PROC_REAL_READ 2
-#define SENSORS_PROC_REAL_WRITE 3
-
-/* These funcion reads or writes a 'real' value (encoded by the combination
-   of an integer and a magnitude, the last is the power of ten the value
-   should be divided with) to a /proc/sys directory. To use these functions,
-   you must (before registering the ctl_table) set the extra2 field to the
-   client, and the extra1 field to a function of the form:
-      void func(struct i2c_client *client, int operation, int ctl_name,
-                int *nrels_mag, long *results)
-   This last function can be called for three values of operation. If
-   operation equals SENSORS_PROC_REAL_INFO, the magnitude should be returned
-   in nrels_mag. If operation equals SENSORS_PROC_REAL_READ, values should
-   be read into results. nrels_mag should return the number of elements
-   read; the maximum number is put in it on entry. Finally, if operation
-   equals SENSORS_PROC_REAL_WRITE, the values in results should be
-   written to the chip. nrels_mag contains on entry the number of elements
-   found.
-   In all cases, client points to the client we wish to interact with,
-   and ctl_name is the SYSCTL id of the file we are accessing. */
-extern int i2c_sysctl_real(ctl_table * table, int *name, int nlen,
-			       void *oldval, size_t * oldlenp,
-			       void *newval, size_t newlen,
-			       void **context);
-extern int i2c_proc_real(ctl_table * ctl, int write, struct file *filp,
-			     void *buffer, size_t * lenp);
-
-
-
-/* These rather complex functions must be called when you want to add or
-   delete an entry in /proc/sys/dev/sensors/chips (not yet implemented). It
-   also creates a new directory within /proc/sys/dev/sensors/.
-   ctl_template should be a template of the newly created directory. It is
-   copied in memory. The extra2 field of each file is set to point to client.
-   If any driver wants subdirectories within the newly created directory,
-   these functions must be updated! */
-extern int i2c_register_entry(struct i2c_client *client,
-				  const char *prefix,
-				  ctl_table * ctl_template);
-
-extern void i2c_deregister_entry(int id);
-
-
-/* A structure containing detect information.
-   Force variables overrule all other variables; they force a detection on
-   that place. If a specific chip is given, the module blindly assumes this
-   chip type is present; if a general force (kind == 0) is given, the module
-   will still try to figure out what type of chip is present. This is useful
-   if for some reasons the detect for SMBus or ISA address space filled
-   fails.
-   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. 
-   kind: The kind of chip. 0 equals any chip.
-*/
-struct i2c_force_data {
-	unsigned short *force;
-	unsigned short kind;
-};
-
-/* A structure containing the detect information.
-   normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
-     A list of I2C addresses which should normally be examined.
-   normal_i2c_range: filled in by the module writer. Terminated by 
-     SENSORS_I2C_END
-     A list of pairs of I2C addresses, each pair being an inclusive range of
-     addresses which should normally be examined.
-   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
-     A list of ISA addresses which should normally be examined.
-   normal_isa_range: filled in by the module writer. Terminated by 
-     SENSORS_ISA_END
-     A list of triples. The first two elements are ISA addresses, being an
-     range of addresses which should normally be examined. The third is the
-     modulo parameter: only addresses which are 0 module this value relative
-     to the first address of the range are actually considered.
-   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. These
-     addresses are also probed, as if they were in the 'normal' list.
-   probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-     values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of addresses that are also probed, as
-     if they were in the 'normal' list.
-   ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
-     addresses are never probed. This parameter overrules 'normal' and 
-     'probe', but not the 'force' lists.
-   ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-      values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of I2C addresses that are never probed.
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
-   force_data: insmod parameters. A list, ending with an element of which
-     the force field is NULL.
-*/
-struct i2c_address_data {
-	unsigned short *normal_i2c;
-	unsigned short *normal_i2c_range;
-	unsigned int *normal_isa;
-	unsigned int *normal_isa_range;
-	unsigned short *probe;
-	unsigned short *probe_range;
-	unsigned short *ignore;
-	unsigned short *ignore_range;
-	struct i2c_force_data *forces;
-};
-
-/* Internal numbers to terminate lists */
-#define SENSORS_I2C_END 0xfffe
-#define SENSORS_ISA_END 0xfffefffe
-
-/* The numbers to use to set an ISA or I2C bus address */
-#define SENSORS_ISA_BUS 9191
-#define SENSORS_ANY_I2C_BUS 0xffff
-
-/* The length of the option lists */
-#define SENSORS_MAX_OPTS 48
-
-/* Default fill of many variables */
-#define SENSORS_DEFAULTS {SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
-                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END}
-
-/* This is ugly. We need to evaluate SENSORS_MAX_OPTS before it is 
-   stringified */
-#define SENSORS_MODPARM_AUX1(x) "1-" #x "h"
-#define SENSORS_MODPARM_AUX(x) SENSORS_MODPARM_AUX1(x)
-#define SENSORS_MODPARM SENSORS_MODPARM_AUX(SENSORS_MAX_OPTS)
-
-/* SENSORS_MODULE_PARM creates a module parameter, and puts it in the
-   module header */
-#define SENSORS_MODULE_PARM(var,desc) \
-  static unsigned short var[SENSORS_MAX_OPTS] = SENSORS_DEFAULTS; \
-  MODULE_PARM(var,SENSORS_MODPARM); \
-  MODULE_PARM_DESC(var,desc)
-
-/* SENSORS_MODULE_PARM creates a 'force_*' module parameter, and puts it in
-   the module header */
-#define SENSORS_MODULE_PARM_FORCE(name) \
-  SENSORS_MODULE_PARM(force_ ## name, \
-                      "List of adapter,address pairs which are unquestionably" \
-                      " assumed to contain a `" # name "' chip")
-
-
-/* This defines several insmod variables, and the addr_data structure */
-#define SENSORS_INSMOD \
-  SENSORS_MODULE_PARM(probe, \
-                      "List of adapter,address pairs to scan additionally"); \
-  SENSORS_MODULE_PARM(probe_range, \
-                      "List of adapter,start-addr,end-addr triples to scan " \
-                      "additionally"); \
-  SENSORS_MODULE_PARM(ignore, \
-                      "List of adapter,address pairs not to scan"); \
-  SENSORS_MODULE_PARM(ignore_range, \
-                      "List of adapter,start-addr,end-addr triples not to " \
-                      "scan"); \
-  static struct i2c_address_data addr_data = \
-                                       {normal_i2c, normal_i2c_range, \
-                                        normal_isa, normal_isa_range, \
-                                        probe, probe_range, \
-                                        ignore, ignore_range, \
-                                        forces}
-
-/* The following functions create an enum with the chip names as elements. 
-   The first element of the enum is any_chip. These are the only macros
-   a module will want to use. */
-
-#define SENSORS_INSMOD_0 \
-  enum chips { any_chip }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_1(chip1) \
-  enum chips { any_chip, chip1 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  static struct i2c_force_data forces[] = {{force,any_chip},\
-                                                 {force_ ## chip1,chip1}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_2(chip1,chip2) \
-  enum chips { any_chip, chip1, chip2 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
-  enum chips { any_chip, chip1, chip2, chip3 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  SENSORS_MODULE_PARM_FORCE(chip7); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {force_ ## chip7,chip7}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
-  SENSORS_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  SENSORS_MODULE_PARM_FORCE(chip7); \
-  SENSORS_MODULE_PARM_FORCE(chip8); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {force_ ## chip7,chip7}, \
-                                                 {force_ ## chip8,chip8}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
-				    int addr, unsigned short flags,
-				    int kind);
-
-/* Detect function. It iterates over all possible addresses itself. For
-   SMBus addresses, it will only call found_proc if some client is connected
-   to the SMBus (unless a 'force' matched); for ISA detections, this is not
-   done. */
-extern int i2c_detect(struct i2c_adapter *adapter,
-			  struct i2c_address_data *address_data,
-			  i2c_found_addr_proc * found_proc);
-
-
-/* This macro is used to scale user-input to sensible values in almost all
-   chip drivers. */
-static inline int SENSORS_LIMIT(long value, long low, long high)
-{
-	if (value < low)
-		return low;
-	else if (value > high)
-		return high;
-	else
-		return value;
-}
-
-
-/* The maximum length of the prefix */
-#define SENSORS_PREFIX_MAX 20
-
-/* Sysctl IDs */
-#ifdef DEV_HWMON
-#define DEV_SENSORS DEV_HWMON
-#else				/* ndef DEV_HWMOM */
-#define DEV_SENSORS 2		/* The id of the lm_sensors directory within the
-				   dev table */
-#endif				/* def DEV_HWMON */
-
-#define SENSORS_CHIPS 1
-struct i2c_chips_data {
-	int sysctl_id;
-	char name[SENSORS_PREFIX_MAX + 13];
-};
-
-#endif				/* def _LINUX_I2C_PROC_H */
-
diff -urN linux-2.5.66-bk8/include/linux/i2c-sensor.h linux-2.5.66-bk9/include/linux/i2c-sensor.h
--- linux-2.5.66-bk8/include/linux/i2c-sensor.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/include/linux/i2c-sensor.h	2003-04-03 04:32:42.000000000 -0800
@@ -0,0 +1,373 @@
+/*
+    i2c-sensor.h - Part of the i2c package
+    was originally sensors.h - Part of lm_sensors, Linux kernel modules
+                               for hardware monitoring
+    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_I2C_SENSOR_H
+#define _LINUX_I2C_SENSOR_H
+
+#include <linux/sysctl.h>
+
+/* The type of callback functions used in sensors_{proc,sysctl}_real */
+typedef void (*i2c_real_callback) (struct i2c_client * client,
+				       int operation, int ctl_name,
+				       int *nrels_mag, long *results);
+
+/* Values for the operation field in the above function type */
+#define SENSORS_PROC_REAL_INFO 1
+#define SENSORS_PROC_REAL_READ 2
+#define SENSORS_PROC_REAL_WRITE 3
+
+/* A structure containing detect information.
+   Force variables overrule all other variables; they force a detection on
+   that place. If a specific chip is given, the module blindly assumes this
+   chip type is present; if a general force (kind == 0) is given, the module
+   will still try to figure out what type of chip is present. This is useful
+   if for some reasons the detect for SMBus or ISA address space filled
+   fails.
+   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second is the address. 
+   kind: The kind of chip. 0 equals any chip.
+*/
+struct i2c_force_data {
+	unsigned short *force;
+	unsigned short kind;
+};
+
+/* A structure containing the detect information.
+   normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
+     A list of I2C addresses which should normally be examined.
+   normal_i2c_range: filled in by the module writer. Terminated by 
+     SENSORS_I2C_END
+     A list of pairs of I2C addresses, each pair being an inclusive range of
+     addresses which should normally be examined.
+   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
+     A list of ISA addresses which should normally be examined.
+   normal_isa_range: filled in by the module writer. Terminated by 
+     SENSORS_ISA_END
+     A list of triples. The first two elements are ISA addresses, being an
+     range of addresses which should normally be examined. The third is the
+     modulo parameter: only addresses which are 0 module this value relative
+     to the first address of the range are actually considered.
+   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second is the address. These
+     addresses are also probed, as if they were in the 'normal' list.
+   probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
+     values.
+     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
+     These form an inclusive range of addresses that are also probed, as
+     if they were in the 'normal' list.
+   ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
+     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
+     addresses are never probed. This parameter overrules 'normal' and 
+     'probe', but not the 'force' lists.
+   ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
+      values.
+     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
+     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
+     These form an inclusive range of I2C addresses that are never probed.
+     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+   force_data: insmod parameters. A list, ending with an element of which
+     the force field is NULL.
+*/
+struct i2c_address_data {
+	unsigned short *normal_i2c;
+	unsigned short *normal_i2c_range;
+	unsigned int *normal_isa;
+	unsigned int *normal_isa_range;
+	unsigned short *probe;
+	unsigned short *probe_range;
+	unsigned short *ignore;
+	unsigned short *ignore_range;
+	struct i2c_force_data *forces;
+};
+
+/* Internal numbers to terminate lists */
+#define SENSORS_I2C_END 0xfffe
+#define SENSORS_ISA_END 0xfffefffe
+
+/* The numbers to use to set an ISA or I2C bus address */
+#define SENSORS_ISA_BUS 9191
+#define SENSORS_ANY_I2C_BUS 0xffff
+
+/* The length of the option lists */
+#define SENSORS_MAX_OPTS 48
+
+/* Default fill of many variables */
+#define SENSORS_DEFAULTS {SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END, \
+                          SENSORS_I2C_END, SENSORS_I2C_END, SENSORS_I2C_END}
+
+/* This is ugly. We need to evaluate SENSORS_MAX_OPTS before it is 
+   stringified */
+#define SENSORS_MODPARM_AUX1(x) "1-" #x "h"
+#define SENSORS_MODPARM_AUX(x) SENSORS_MODPARM_AUX1(x)
+#define SENSORS_MODPARM SENSORS_MODPARM_AUX(SENSORS_MAX_OPTS)
+
+/* SENSORS_MODULE_PARM creates a module parameter, and puts it in the
+   module header */
+#define SENSORS_MODULE_PARM(var,desc) \
+  static unsigned short var[SENSORS_MAX_OPTS] = SENSORS_DEFAULTS; \
+  MODULE_PARM(var,SENSORS_MODPARM); \
+  MODULE_PARM_DESC(var,desc)
+
+/* SENSORS_MODULE_PARM creates a 'force_*' module parameter, and puts it in
+   the module header */
+#define SENSORS_MODULE_PARM_FORCE(name) \
+  SENSORS_MODULE_PARM(force_ ## name, \
+                      "List of adapter,address pairs which are unquestionably" \
+                      " assumed to contain a `" # name "' chip")
+
+
+/* This defines several insmod variables, and the addr_data structure */
+#define SENSORS_INSMOD \
+  SENSORS_MODULE_PARM(probe, \
+                      "List of adapter,address pairs to scan additionally"); \
+  SENSORS_MODULE_PARM(probe_range, \
+                      "List of adapter,start-addr,end-addr triples to scan " \
+                      "additionally"); \
+  SENSORS_MODULE_PARM(ignore, \
+                      "List of adapter,address pairs not to scan"); \
+  SENSORS_MODULE_PARM(ignore_range, \
+                      "List of adapter,start-addr,end-addr triples not to " \
+                      "scan"); \
+  static struct i2c_address_data addr_data = \
+                                       {normal_i2c, normal_i2c_range, \
+                                        normal_isa, normal_isa_range, \
+                                        probe, probe_range, \
+                                        ignore, ignore_range, \
+                                        forces}
+
+/* The following functions create an enum with the chip names as elements. 
+   The first element of the enum is any_chip. These are the only macros
+   a module will want to use. */
+
+#define SENSORS_INSMOD_0 \
+  enum chips { any_chip }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_1(chip1) \
+  enum chips { any_chip, chip1 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  static struct i2c_force_data forces[] = {{force,any_chip},\
+                                                 {force_ ## chip1,chip1}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_2(chip1,chip2) \
+  enum chips { any_chip, chip1, chip2 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
+  enum chips { any_chip, chip1, chip2, chip3 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
+  enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  SENSORS_MODULE_PARM_FORCE(chip4); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {force_ ## chip4,chip4}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
+  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  SENSORS_MODULE_PARM_FORCE(chip4); \
+  SENSORS_MODULE_PARM_FORCE(chip5); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {force_ ## chip4,chip4}, \
+                                                 {force_ ## chip5,chip5}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
+  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  SENSORS_MODULE_PARM_FORCE(chip4); \
+  SENSORS_MODULE_PARM_FORCE(chip5); \
+  SENSORS_MODULE_PARM_FORCE(chip6); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {force_ ## chip4,chip4}, \
+                                                 {force_ ## chip5,chip5}, \
+                                                 {force_ ## chip6,chip6}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
+  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  SENSORS_MODULE_PARM_FORCE(chip4); \
+  SENSORS_MODULE_PARM_FORCE(chip5); \
+  SENSORS_MODULE_PARM_FORCE(chip6); \
+  SENSORS_MODULE_PARM_FORCE(chip7); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {force_ ## chip4,chip4}, \
+                                                 {force_ ## chip5,chip5}, \
+                                                 {force_ ## chip6,chip6}, \
+                                                 {force_ ## chip7,chip7}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
+  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
+  SENSORS_MODULE_PARM(force, \
+                      "List of adapter,address pairs to boldly assume " \
+                      "to be present"); \
+  SENSORS_MODULE_PARM_FORCE(chip1); \
+  SENSORS_MODULE_PARM_FORCE(chip2); \
+  SENSORS_MODULE_PARM_FORCE(chip3); \
+  SENSORS_MODULE_PARM_FORCE(chip4); \
+  SENSORS_MODULE_PARM_FORCE(chip5); \
+  SENSORS_MODULE_PARM_FORCE(chip6); \
+  SENSORS_MODULE_PARM_FORCE(chip7); \
+  SENSORS_MODULE_PARM_FORCE(chip8); \
+  static struct i2c_force_data forces[] = {{force,any_chip}, \
+                                                 {force_ ## chip1,chip1}, \
+                                                 {force_ ## chip2,chip2}, \
+                                                 {force_ ## chip3,chip3}, \
+                                                 {force_ ## chip4,chip4}, \
+                                                 {force_ ## chip5,chip5}, \
+                                                 {force_ ## chip6,chip6}, \
+                                                 {force_ ## chip7,chip7}, \
+                                                 {force_ ## chip8,chip8}, \
+                                                 {NULL}}; \
+  SENSORS_INSMOD
+
+typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
+				    int addr, int kind);
+
+/* Detect function. It iterates over all possible addresses itself. For
+   SMBus addresses, it will only call found_proc if some client is connected
+   to the SMBus (unless a 'force' matched); for ISA detections, this is not
+   done. */
+extern int i2c_detect(struct i2c_adapter *adapter,
+			  struct i2c_address_data *address_data,
+			  i2c_found_addr_proc * found_proc);
+
+
+/* This macro is used to scale user-input to sensible values in almost all
+   chip drivers. */
+static inline int SENSORS_LIMIT(long value, long low, long high)
+{
+	if (value < low)
+		return low;
+	else if (value > high)
+		return high;
+	else
+		return value;
+}
+
+
+/* The maximum length of the prefix */
+#define SENSORS_PREFIX_MAX 20
+
+/* Sysctl IDs */
+#ifdef DEV_HWMON
+#define DEV_SENSORS DEV_HWMON
+#else				/* ndef DEV_HWMOM */
+#define DEV_SENSORS 2		/* The id of the lm_sensors directory within the
+				   dev table */
+#endif				/* def DEV_HWMON */
+
+#define SENSORS_CHIPS 1
+struct i2c_chips_data {
+	int sysctl_id;
+	char name[SENSORS_PREFIX_MAX + 13];
+};
+
+#endif				/* def _LINUX_I2C_SENSOR_H */
+
diff -urN linux-2.5.66-bk8/include/linux/i2c-vid.h linux-2.5.66-bk9/include/linux/i2c-vid.h
--- linux-2.5.66-bk8/include/linux/i2c-vid.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.66-bk9/include/linux/i2c-vid.h	2003-04-03 04:32:42.000000000 -0800
@@ -0,0 +1,62 @@
+/*
+    i2c-vid.h - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    With assistance from Trent Piepho <xyzzy@speakeasy.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    This file contains common code for decoding VID pins.
+    This file is #included in various chip drivers in this directory.
+    As the user is unlikely to load more than one driver which
+    includes this code we don't worry about the wasted space.
+    Reference: VRM x.y DC-DC Converter Design Guidelines,
+    available at http://developer.intel.com
+*/
+
+/*
+    Legal val values 00 - 1F.
+    vrm is the Intel VRM document version.
+    Note: vrm version is scaled by 10 and the return value is scaled by 1000
+    to avoid floating point in the kernel.
+*/
+
+#define DEFAULT_VRM	82
+
+static inline int vid_from_reg(int val, int vrm)
+{
+	switch(vrm) {
+
+	case 91:		/* VRM 9.1 */
+	case 90:		/* VRM 9.0 */
+		return(val == 0x1f ? 0 :
+		                       1850 - val * 25);
+
+	case 85:		/* VRM 8.5 */
+		return((val & 0x10  ? 25 : 0) +
+		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+		       ((val & 0x0f) * 50));
+
+	case 84:		/* VRM 8.4 */
+		val &= 0x0f;
+				/* fall through */
+	default:		/* VRM 8.2 */
+		return(val == 0x1f ? 0 :
+		       val & 0x10  ? 5100 - (val) * 100 :
+		                     2050 - (val) * 50);
+	}
+}
diff -urN linux-2.5.66-bk8/include/linux/module.h linux-2.5.66-bk9/include/linux/module.h
--- linux-2.5.66-bk8/include/linux/module.h	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/include/linux/module.h	2003-04-03 04:32:42.000000000 -0800
@@ -183,7 +183,7 @@
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
-	unsigned int num_ksyms;
+	unsigned int num_syms;
 	const unsigned long *crcs;
 
 	/* GPL-only exported symbols. */
@@ -233,7 +233,7 @@
 #ifdef CONFIG_KALLSYMS
 	/* We keep the symbol and string tables for kallsyms. */
 	Elf_Sym *symtab;
-	unsigned long num_syms;
+	unsigned long num_symtab;
 	char *strtab;
 #endif
 
diff -urN linux-2.5.66-bk8/kernel/module.c linux-2.5.66-bk9/kernel/module.c
--- linux-2.5.66-bk8/kernel/module.c	2003-04-03 04:32:39.000000000 -0800
+++ linux-2.5.66-bk9/kernel/module.c	2003-04-03 04:32:42.000000000 -0800
@@ -156,7 +156,7 @@
 	/* Now try modules. */ 
 	list_for_each_entry(mod, &modules, list) {
 		*owner = mod;
-		for (i = 0; i < mod->num_ksyms; i++)
+		for (i = 0; i < mod->num_syms; i++)
 			if (strcmp(mod->syms[i].name, name) == 0) {
 				*crc = symversion(mod->crcs, i);
 				return mod->syms[i].value;
@@ -839,12 +839,13 @@
 					  unsigned int versindex,
 					  struct module *mod)
 {
-	unsigned int i;
-	struct kernel_symbol_group *ksg;
+	const unsigned long *crc;
+	struct module *owner;
 
-	if (!__find_symbol("struct_module", &ksg, &i, 1))
+	if (!__find_symbol("struct_module", &owner, &crc, 1))
 		BUG();
-	return check_version(sechdrs, versindex, "struct_module", mod, ksg, i);
+	return check_version(sechdrs, versindex, "struct_module", mod,
+			     crc);
 }
 
 /* First part is kernel version, which we ignore. */
@@ -1283,7 +1284,8 @@
 		mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
 
 #ifdef CONFIG_MODVERSIONS
-	if ((mod->num_ksyms&&!crcindex) || (mod->num_gpl_syms&&!gplcrcindex)) {
+	if ((mod->num_syms && !crcindex) || 
+	    (mod->num_gpl_syms && !gplcrcindex)) {
 		printk(KERN_WARNING "%s: No versions for exported symbols."
 		       " Tainting kernel.\n", mod->name);
 		tainted |= TAINT_FORCED_MODULE;
@@ -1309,7 +1311,7 @@
 
 #ifdef CONFIG_KALLSYMS
 	mod->symtab = (void *)sechdrs[symindex].sh_addr;
-	mod->num_syms = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
+	mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
 	mod->strtab = (void *)sechdrs[strindex].sh_addr;
 #endif
 	err = module_finalize(hdr, sechdrs, mod);
@@ -1452,7 +1454,7 @@
 
 	/* Scan for closest preceeding symbol, and next symbol. (ELF
            starts real symbols at 1). */
-	for (i = 1; i < mod->num_syms; i++) {
+	for (i = 1; i < mod->num_symtab; i++) {
 		if (mod->symtab[i].st_shndx == SHN_UNDEF)
 			continue;
 
diff -urN linux-2.5.66-bk8/scripts/Makefile.modpost linux-2.5.66-bk9/scripts/Makefile.modpost
--- linux-2.5.66-bk8/scripts/Makefile.modpost	2003-03-24 14:00:45.000000000 -0800
+++ linux-2.5.66-bk9/scripts/Makefile.modpost	2003-04-03 04:32:42.000000000 -0800
@@ -35,10 +35,11 @@
 # Compile version info for unresolved symbols
 
 quiet_cmd_cc_o_c = CC      $@
-      cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $<
+      cmd_cc_o_c = $(CC) -Wp,-MD,$(depfile) $(CFLAGS) $(CFLAGS_MODULE)	\
+		   -c -o $@ $<
 
 $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
-	$(call if_changed,cc_o_c)
+	$(call if_changed_dep,cc_o_c)
 
 targets += $(modules:.ko=.mod.o)
 
