diff options
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.16')
36 files changed, 0 insertions, 46868 deletions
diff --git a/packages/linux/ixp4xx-kernel/2.6.16/.mtn2git_empty b/packages/linux/ixp4xx-kernel/2.6.16/.mtn2git_empty deleted file mode 100644 index e69de29bb2..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/.mtn2git_empty +++ /dev/null diff --git a/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch b/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch deleted file mode 100644 index eca681b0aa..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-2.6.15/Makefile~ 2006-02-15 00:04:58.000000000 +1030 -+++ linux-2.6.15/Makefile 2006-02-15 00:05:17.000000000 +1030 -@@ -1,7 +1,7 @@ - VERSION = 2 - PATCHLEVEL = 6 - SUBLEVEL = 16 --EXTRAVERSION = -rc4-git9 -+EXTRAVERSION = - NAME=Sliding Snow Leopard - - # *DOCUMENTATION* diff --git a/packages/linux/ixp4xx-kernel/2.6.16/10-ixp4xx-fix-irq.patch b/packages/linux/ixp4xx-kernel/2.6.16/10-ixp4xx-fix-irq.patch deleted file mode 100644 index 4326df2add..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/10-ixp4xx-fix-irq.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- - arch/arm/mach-ixp4xx/common.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/common.c 2006-03-18 18:10:56.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/common.c 2006-03-18 18:48:46.000000000 +0100 -@@ -91,7 +91,7 @@ static void ixp4xx_config_irq(unsigned i - /* - * IRQ -> GPIO mapping table - */ --static int irq2gpio[32] = { -+static char irq2gpio[32] = { - -1, -1, -1, -1, -1, -1, 0, 1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2, 3, 4, 5, 6, -@@ -153,6 +153,9 @@ static int ixp4xx_set_irq_type(unsigned - /* Set the new style */ - *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); - -+ /* Configure the line as an input */ -+ gpio_line_config(line, IXP4XX_GPIO_IN); -+ - return 0; - } - diff --git a/packages/linux/ixp4xx-kernel/2.6.16/11-mtdpart-redboot-config-byteswap.patch b/packages/linux/ixp4xx-kernel/2.6.16/11-mtdpart-redboot-config-byteswap.patch deleted file mode 100644 index e258567462..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/11-mtdpart-redboot-config-byteswap.patch +++ /dev/null @@ -1,74 +0,0 @@ -A more robust test for swapped RedBoot FIS directory partitions. This -changes the test to check the flash_base value for the FIS directory, -since we know where the FIS directory base is we can work out whether -the flash address stored in the directory itself is byte swapped under -most circumstances. If the value is 0 the directory is at the start -of the flash and the test fails. In this case the fallback is to use -the original test made slightly more robust. - -Signed-off-by: John Bowler <jbowler@acm.org> - ---- linux-2.6.15/drivers/mtd/redboot.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/mtd/redboot.c 1970-01-01 00:00:00.000000000 +0000 -@@ -91,14 +91,41 @@ static int parse_redboot_partitions(stru - } - if (!memcmp(buf[i].name, "FIS directory", 14)) { - /* This is apparently the FIS directory entry for the -- * FIS directory itself. The FIS directory size is -- * one erase block; if the buf[i].size field is -- * swab32(erasesize) then we know we are looking at -- * a byte swapped FIS directory - swap all the entries! -- * (NOTE: this is 'size' not 'data_length'; size is -- * the full size of the entry.) -+ * FIS directory itself. To discover whether the entries -+ * in this are native byte sex or byte swapped look at -+ * the flash_base field - we know the FIS directory is -+ * at 'offset' within the flash. - */ -- if (swab32(buf[i].size) == master->erasesize) { -+ int maybe_native, maybe_swapped; -+ if (fis_origin != 0) { -+ maybe_native = -+ buf[i].flash_base == fis_origin + offset; -+ maybe_swapped = -+ swab32(buf[i].flash_base) == fis_origin + offset; -+ } else if (offset != 0 || buf[i].flash_base != 0) { -+ maybe_native = -+ (buf[i].flash_base & (master->size-1)) == offset; -+ maybe_swapped = -+ (swab32(buf[i].flash_base) & (master->size-1)) == offset; -+ } else { -+ /* The FIS directory is at the start of the flash and -+ * the 'flash_base' field is 0. The critical case is when -+ * we are booting off this flash, but then we don't expect -+ * this because the boot loader is pretty much always at -+ * the start! Since the FIS directory is always less than -+ * or equal to one erase block do the following: -+ */ -+ maybe_native = buf[i].size <= master->erasesize; -+ maybe_swapped = swab32(buf[i].size) <= master->erasesize; -+ } -+ -+ if (maybe_native && maybe_swapped) -+ printk(KERN_WARNING "RedBoot directory 0x%lx(0x%lx) assumed native\n", -+ buf[i].flash_base, buf[i].size); -+ else if (!maybe_native && !maybe_swapped) -+ printk(KERN_ERR "RedBoot directory 0x%lx(0x%lx) forced native\n", -+ buf[i].flash_base, buf[i].size); -+ else if (maybe_swapped) { - int j; - for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) { - /* The unsigned long fields were written with the -@@ -112,7 +139,11 @@ static int parse_redboot_partitions(stru - swab32s(&buf[j].desc_cksum); - swab32s(&buf[j].file_cksum); - } -- } -+ printk(KERN_NOTICE "RedBoot directory 0x%lx(0x%lx) swapped\n", -+ buf[i].flash_base, buf[i].size); -+ } else -+ printk(KERN_NOTICE "RedBoot directory 0x%lx(0x%lx) native\n", -+ buf[i].flash_base, buf[i].size); - break; - } - } diff --git a/packages/linux/ixp4xx-kernel/2.6.16/15-jffs2-endian-config.patch b/packages/linux/ixp4xx-kernel/2.6.16/15-jffs2-endian-config.patch deleted file mode 100644 index 893353ef4f..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/15-jffs2-endian-config.patch +++ /dev/null @@ -1,85 +0,0 @@ -This patch allows the endianness of the JFSS2 filesystem to be -specified by config options. - -It defaults to native-endian (the previously hard-coded option). - -Some architectures (in particular, the NSLU2) benefit from having a -single known endianness of JFFS2 filesystem (for data, not -executables) independent of the endianness of the processor (ARM -processors can be switched to either endianness at run-time). - -Signed-off-by: Rod Whitby <rod@whitby.id.au> -Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> - - fs/Kconfig | 25 +++++++++++++++++++++++++ - fs/jffs2/nodelist.h | 8 +++----- - 2 files changed, 28 insertions(+), 5 deletions(-) - ---- linux-nslu2.orig/fs/Kconfig 2006-02-06 20:38:09.000000000 +0100 -+++ linux-nslu2/fs/Kconfig 2006-02-06 21:49:07.000000000 +0100 -@@ -1174,6 +1174,31 @@ config JFFS2_CMODE_SIZE - - endchoice - -+choice -+ prompt "JFFS2 endianness" -+ default JFFS2_NATIVE_ENDIAN -+ depends on JFFS2_FS -+ help -+ You can set here the default endianness of JFFS2 from -+ the available options. Don't touch if unsure. -+ -+config JFFS2_NATIVE_ENDIAN -+ bool "native endian" -+ help -+ Uses a native endian bytestream. -+ -+config JFFS2_BIG_ENDIAN -+ bool "big endian" -+ help -+ Uses a big endian bytestream. -+ -+config JFFS2_LITTLE_ENDIAN -+ bool "little endian" -+ help -+ Uses a little endian bytestream. -+ -+endchoice -+ - config CRAMFS - tristate "Compressed ROM file system support (cramfs)" - select ZLIB_INFLATE ---- linux-nslu2.orig/fs/jffs2/nodelist.h 2006-02-06 20:35:36.000000000 +0100 -+++ linux-nslu2/fs/jffs2/nodelist.h 2006-02-06 21:49:07.000000000 +0100 -@@ -29,12 +29,10 @@ - #include "os-linux.h" - #endif - --#define JFFS2_NATIVE_ENDIAN -- - /* Note we handle mode bits conversion from JFFS2 (i.e. Linux) to/from - whatever OS we're actually running on here too. */ - --#if defined(JFFS2_NATIVE_ENDIAN) -+#if defined(CONFIG_JFFS2_NATIVE_ENDIAN) - #define cpu_to_je16(x) ((jint16_t){x}) - #define cpu_to_je32(x) ((jint32_t){x}) - #define cpu_to_jemode(x) ((jmode_t){os_to_jffs2_mode(x)}) -@@ -42,7 +40,7 @@ - #define je16_to_cpu(x) ((x).v16) - #define je32_to_cpu(x) ((x).v32) - #define jemode_to_cpu(x) (jffs2_to_os_mode((x).m)) --#elif defined(JFFS2_BIG_ENDIAN) -+#elif defined(CONFIG_JFFS2_BIG_ENDIAN) - #define cpu_to_je16(x) ((jint16_t){cpu_to_be16(x)}) - #define cpu_to_je32(x) ((jint32_t){cpu_to_be32(x)}) - #define cpu_to_jemode(x) ((jmode_t){cpu_to_be32(os_to_jffs2_mode(x))}) -@@ -50,7 +48,7 @@ - #define je16_to_cpu(x) (be16_to_cpu(x.v16)) - #define je32_to_cpu(x) (be32_to_cpu(x.v32)) - #define jemode_to_cpu(x) (be32_to_cpu(jffs2_to_os_mode((x).m))) --#elif defined(JFFS2_LITTLE_ENDIAN) -+#elif defined(CONFIG_JFFS2_LITTLE_ENDIAN) - #define cpu_to_je16(x) ((jint16_t){cpu_to_le16(x)}) - #define cpu_to_je32(x) ((jint32_t){cpu_to_le32(x)}) - #define cpu_to_jemode(x) ((jmode_t){cpu_to_le32(os_to_jffs2_mode(x))}) diff --git a/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch b/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch deleted file mode 100644 index 044bd3abc1..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch +++ /dev/null @@ -1,5846 +0,0 @@ ---- - CREDITS | 5 - MAINTAINERS | 6 - arch/arm/Kconfig | 3 - arch/arm/common/rtctime.c | 108 -- - arch/arm/mach-integrator/time.c | 16 - arch/arm/mach-pxa/generic.c | 6 - arch/arm/mach-sa1100/generic.c | 6 - arch/mips/ddb5xxx/common/rtc_ds1386.c | 4 - arch/mips/dec/time.c | 4 - arch/mips/ite-boards/generic/time.c | 4 - arch/mips/jmr3927/common/rtc_ds1742.c | 4 - arch/mips/kernel/time.c | 22 - arch/mips/lasat/setup.c | 4 - arch/mips/mips-boards/atlas/atlas_setup.c | 2 - arch/mips/mips-boards/malta/malta_setup.c | 2 - arch/mips/momentum/jaguar_atx/setup.c | 4 - arch/mips/momentum/ocelot_3/setup.c | 4 - arch/mips/momentum/ocelot_c/setup.c | 4 - arch/mips/pmc-sierra/yosemite/setup.c | 4 - arch/mips/sgi-ip22/ip22-time.c | 4 - arch/mips/sgi-ip32/ip32-setup.c | 4 - arch/mips/sibyte/swarm/setup.c | 8 - arch/mips/sni/setup.c | 4 - arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c | 4 - arch/mips/tx4938/common/rtc_rx5c348.c | 4 - drivers/Kconfig | 2 - drivers/Makefile | 1 - drivers/char/Kconfig | 2 - drivers/i2c/chips/Kconfig | 18 - drivers/i2c/chips/Makefile | 2 - drivers/i2c/chips/rtc8564.c | 385 ------- - drivers/i2c/chips/rtc8564.h | 78 - - drivers/i2c/chips/x1205.c | 698 ------------- - drivers/rtc/Kconfig | 156 ++ - drivers/rtc/Makefile | 20 - drivers/rtc/class.c | 145 ++ - drivers/rtc/hctosys.c | 69 + - drivers/rtc/interface.c | 277 +++++ - drivers/rtc/rtc-dev.c | 382 +++++++ - drivers/rtc/rtc-ds1672.c | 233 ++++ - drivers/rtc/rtc-ep93xx.c | 163 +++ - drivers/rtc/rtc-lib.c | 99 + - drivers/rtc/rtc-pcf8563.c | 355 ++++++ - drivers/rtc/rtc-proc.c | 162 +++ - drivers/rtc/rtc-rs5c372.c | 295 +++++ - drivers/rtc/rtc-sa1100.c | 392 +++++++ - drivers/rtc/rtc-sysfs.c | 124 ++ - drivers/rtc/rtc-test.c | 205 +++ - drivers/rtc/rtc-x1205.c | 619 +++++++++++ - include/asm-arm/rtc.h | 3 - include/asm-mips/time.h | 12 - include/linux/rtc.h | 92 + - include/linux/x1205.h | 31 - 53 files changed, 3888 insertions(+), 1372 deletions(-) - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-lib.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,99 @@ -+/* -+ * rtc and date/time utility functions -+ * -+ * Copyright (C) 2005-06 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on arch/arm/common/rtctime.c and other bits -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+ -+static const unsigned char rtc_days_in_month[] = { -+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -+}; -+ -+#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) -+#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) -+ -+int rtc_month_days(unsigned int month, unsigned int year) -+{ -+ return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); -+} -+EXPORT_SYMBOL(rtc_month_days); -+ -+/* -+ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. -+ */ -+void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) -+{ -+ register int days, month, year; -+ -+ days = time / 86400; -+ time -= days * 86400; -+ -+ /* day of the week, 1970-01-01 was a Thursday */ -+ tm->tm_wday = (days + 4) % 7; -+ -+ year = 1970 + days / 365; -+ days -= (year - 1970) * 365 -+ + LEAPS_THRU_END_OF(year - 1) -+ - LEAPS_THRU_END_OF(1970 - 1); -+ if (days < 0) { -+ year -= 1; -+ days += 365 + LEAP_YEAR(year); -+ } -+ tm->tm_year = year - 1900; -+ tm->tm_yday = days + 1; -+ -+ for (month = 0; month < 11; month++) { -+ int newdays; -+ -+ newdays = days - rtc_month_days(month, year); -+ if (newdays < 0) -+ break; -+ days = newdays; -+ } -+ tm->tm_mon = month; -+ tm->tm_mday = days + 1; -+ -+ tm->tm_hour = time / 3600; -+ time -= tm->tm_hour * 3600; -+ tm->tm_min = time / 60; -+ tm->tm_sec = time - tm->tm_min * 60; -+} -+EXPORT_SYMBOL(rtc_time_to_tm); -+ -+/* -+ * Does the rtc_time represent a valid date/time? -+ */ -+int rtc_valid_tm(struct rtc_time *tm) -+{ -+ if (tm->tm_year < 70 -+ || tm->tm_mon >= 12 -+ || tm->tm_mday < 1 -+ || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) -+ || tm->tm_hour >= 24 -+ || tm->tm_min >= 60 -+ || tm->tm_sec >= 60) -+ return -EINVAL; -+ -+ return 0; -+} -+EXPORT_SYMBOL(rtc_valid_tm); -+ -+/* -+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00. -+ */ -+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) -+{ -+ *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, -+ tm->tm_hour, tm->tm_min, tm->tm_sec); -+ return 0; -+} -+EXPORT_SYMBOL(rtc_tm_to_time); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/Makefile 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,20 @@ -+# -+# Makefile for RTC class/drivers. -+# -+ -+obj-$(CONFIG_RTC_LIB) += rtc-lib.o -+obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o -+obj-$(CONFIG_RTC_CLASS) += rtc-core.o -+rtc-core-y := class.o interface.o -+ -+obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o -+obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o -+obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o -+ -+obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o -+obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -+obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o -+obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o -+obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o -+obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o -+obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/Kconfig 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,156 @@ -+\# -+# RTC class/drivers configuration -+# -+ -+menu "Real Time Clock" -+ -+config RTC_LIB -+ bool -+ -+config RTC_CLASS -+ tristate "RTC class" -+ depends on EXPERIMENTAL -+ default n -+ select RTC_LIB -+ help -+ Generic RTC class support. If you say yes here, you will -+ be allowed to plug one or more RTCs to your system. You will -+ probably want to enable one of more of the interfaces below. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-class. -+ -+config RTC_HCTOSYS -+ bool "Set system time from RTC on startup" -+ depends on RTC_CLASS = y -+ default y -+ help -+ If you say yes here, the system time will be set using -+ the value read from the specified RTC device. This is useful -+ in order to avoid unnecessary fschk runs. -+ -+config RTC_HCTOSYS_DEVICE -+ string "The RTC to read the time from" -+ depends on RTC_HCTOSYS = y -+ default "rtc0" -+ help -+ The RTC device that will be used as the source for -+ the system time, usually rtc0. -+ -+comment "RTC interfaces" -+ depends on RTC_CLASS -+ -+config RTC_INTF_SYSFS -+ tristate "sysfs" -+ depends on RTC_CLASS && SYSFS -+ default RTC_CLASS -+ help -+ Say yes here if you want to use your RTC using the sysfs -+ interface, /sys/class/rtc/rtcX . -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-sysfs. -+ -+config RTC_INTF_PROC -+ tristate "proc" -+ depends on RTC_CLASS && PROC_FS -+ default RTC_CLASS -+ help -+ Say yes here if you want to use your RTC using the proc -+ interface, /proc/driver/rtc . -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-proc. -+ -+config RTC_INTF_DEV -+ tristate "dev" -+ depends on RTC_CLASS -+ default RTC_CLASS -+ help -+ Say yes here if you want to use your RTC using the dev -+ interface, /dev/rtc . -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-dev. -+ -+comment "RTC drivers" -+ depends on RTC_CLASS -+ -+config RTC_DRV_X1205 -+ tristate "Xicor/Intersil X1205 RTC chip" -+ depends on RTC_CLASS && I2C -+ help -+ If you say yes here you get support for the -+ Xicor/Intersil X1205 RTC chip. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-x1205. -+ -+config RTC_DRV_DS1672 -+ tristate "Dallas/Maxim DS1672" -+ depends on RTC_CLASS && I2C -+ help -+ If you say yes here you get support for the -+ Dallas/Maxim DS1672 timekeeping chip. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-ds1672. -+ -+config RTC_DRV_PCF8563 -+ tristate "Philips PCF8563/Epson RTC8564" -+ depends on RTC_CLASS && I2C -+ help -+ If you say yes here you get support for the -+ Philips PCF8563 RTC chip. The Epson RTC8564 -+ should work as well. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-pcf8563. -+ -+config RTC_DRV_RS5C372 -+ tristate "Ricoh RS5C372A/B" -+ depends on RTC_CLASS && I2C -+ help -+ If you say yes here you get support for the -+ Ricoh RS5C372A and RS5C372B RTC chips. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-rs5c372. -+ -+config RTC_DRV_EP93XX -+ tristate "Cirrus Logic EP93XX" -+ depends on RTC_CLASS && ARCH_EP93XX -+ help -+ If you say yes here you get support for the -+ RTC embedded in the Cirrus Logic EP93XX processors. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-ep93xx. -+ -+ -+config RTC_DRV_SA1100 -+ bool "SA11x0/PXA2xx RTC support" -+ depends on ARCH_SA1100 || ARCH_PXA -+ help -+ If you say Y here you will get access to the real time clock -+ built into your SA11x0 or PXA2xx CPU. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called rtc-sa1100. -+ -+config RTC_DRV_TEST -+ tristate "Test driver/device" -+ depends on RTC_CLASS -+ help -+ If you say yes here you get support for the -+ RTC test driver. It's a software RTC which can be -+ used to test the RTC subsystem APIs. It gets -+ the time from the system clock. -+ You want this driver only if you are doing development -+ on the RTC subsystem. Please read the source code -+ for further details. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-test. -+ -+endmenu ---- linux-ixp4xx.orig/drivers/Kconfig 2006-03-08 01:59:18.000000000 +0100 -+++ linux-ixp4xx/drivers/Kconfig 2006-03-08 01:59:26.000000000 +0100 -@@ -72,4 +72,6 @@ source "drivers/sn/Kconfig" - - source "drivers/edac/Kconfig" - -+source "drivers/rtc/Kconfig" -+ - endmenu ---- linux-ixp4xx.orig/drivers/Makefile 2006-03-08 01:59:18.000000000 +0100 -+++ linux-ixp4xx/drivers/Makefile 2006-03-08 01:59:26.000000000 +0100 -@@ -56,6 +56,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/ - obj-$(CONFIG_GAMEPORT) += input/gameport/ - obj-$(CONFIG_INPUT) += input/ - obj-$(CONFIG_I2O) += message/ -+obj-$(CONFIG_RTC_LIB) += rtc/ - obj-$(CONFIG_I2C) += i2c/ - obj-$(CONFIG_W1) += w1/ - obj-$(CONFIG_HWMON) += hwmon/ ---- linux-ixp4xx.orig/include/linux/rtc.h 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/include/linux/rtc.h 2006-03-08 01:59:26.000000000 +0100 -@@ -93,8 +93,100 @@ struct rtc_pll_info { - #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ - #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ - -+/* interrupt flags */ -+#define RTC_IRQF 0x80 /* any of the following is active */ -+#define RTC_PF 0x40 -+#define RTC_AF 0x20 -+#define RTC_UF 0x10 -+ - #ifdef __KERNEL__ - -+extern int rtc_month_days(unsigned int month, unsigned int year); -+extern int rtc_valid_tm(struct rtc_time *tm); -+extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time); -+extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); -+ -+#include <linux/device.h> -+#include <linux/seq_file.h> -+#include <linux/cdev.h> -+#include <linux/poll.h> -+#include <linux/mutex.h> -+ -+extern struct class *rtc_class; -+ -+struct rtc_class_ops { -+ int (*open)(struct device *); -+ void (*release)(struct device *); -+ int (*ioctl)(struct device *, unsigned int, unsigned long); -+ int (*read_time)(struct device *, struct rtc_time *); -+ int (*set_time)(struct device *, struct rtc_time *); -+ int (*read_alarm)(struct device *, struct rtc_wkalrm *); -+ int (*set_alarm)(struct device *, struct rtc_wkalrm *); -+ int (*proc)(struct device *, struct seq_file *); -+ int (*set_mmss)(struct device *, unsigned long secs); -+ int (*irq_set_state)(struct device *, int enabled); -+ int (*irq_set_freq)(struct device *, int freq); -+ int (*read_callback)(struct device *, int data); -+}; -+ -+#define RTC_DEVICE_NAME_SIZE 20 -+struct rtc_task; -+ -+struct rtc_device -+{ -+ struct class_device class_dev; -+ struct module *owner; -+ -+ int id; -+ char name[RTC_DEVICE_NAME_SIZE]; -+ -+ struct rtc_class_ops *ops; -+ struct mutex ops_lock; -+ -+ struct class_device *rtc_dev; -+ struct cdev char_dev; -+ struct mutex char_lock; -+ -+ unsigned long irq_data; -+ spinlock_t irq_lock; -+ wait_queue_head_t irq_queue; -+ struct fasync_struct *async_queue; -+ -+ struct rtc_task *irq_task; -+ spinlock_t irq_task_lock; -+ int irq_freq; -+}; -+#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev) -+ -+extern struct rtc_device *rtc_device_register(const char *name, -+ struct device *dev, -+ struct rtc_class_ops *ops, -+ struct module *owner); -+extern void rtc_device_unregister(struct rtc_device *rdev); -+extern int rtc_interface_register(struct class_interface *intf); -+ -+extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm); -+extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm); -+extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs); -+extern int rtc_read_alarm(struct class_device *class_dev, -+ struct rtc_wkalrm *alrm); -+extern int rtc_set_alarm(struct class_device *class_dev, -+ struct rtc_wkalrm *alrm); -+extern void rtc_update_irq(struct class_device *class_dev, -+ unsigned long num, unsigned long events); -+ -+extern struct class_device *rtc_class_open(char *name); -+extern void rtc_class_close(struct class_device *class_dev); -+ -+extern int rtc_irq_register(struct class_device *class_dev, -+ struct rtc_task *task); -+extern void rtc_irq_unregister(struct class_device *class_dev, -+ struct rtc_task *task); -+extern int rtc_irq_set_state(struct class_device *class_dev, -+ struct rtc_task *task, int enabled); -+extern int rtc_irq_set_freq(struct class_device *class_dev, -+ struct rtc_task *task, int freq); -+ - typedef struct rtc_task { - void (*func)(void *private_data); - void *private_data; ---- linux-ixp4xx.orig/arch/arm/common/rtctime.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/arm/common/rtctime.c 2006-03-08 01:59:26.000000000 +0100 -@@ -20,6 +20,7 @@ - #include <linux/capability.h> - #include <linux/device.h> - #include <linux/mutex.h> -+#include <linux/rtc.h> - - #include <asm/rtc.h> - #include <asm/semaphore.h> -@@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops; - - #define rtc_epoch 1900UL - --static const unsigned char days_in_month[] = { -- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 --}; -- --#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) --#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) -- --static int month_days(unsigned int month, unsigned int year) --{ -- return days_in_month[month] + (LEAP_YEAR(year) && month == 1); --} -- --/* -- * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. -- */ --void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) --{ -- int days, month, year; -- -- days = time / 86400; -- time -= days * 86400; -- -- tm->tm_wday = (days + 4) % 7; -- -- year = 1970 + days / 365; -- days -= (year - 1970) * 365 -- + LEAPS_THRU_END_OF(year - 1) -- - LEAPS_THRU_END_OF(1970 - 1); -- if (days < 0) { -- year -= 1; -- days += 365 + LEAP_YEAR(year); -- } -- tm->tm_year = year - 1900; -- tm->tm_yday = days + 1; -- -- for (month = 0; month < 11; month++) { -- int newdays; -- -- newdays = days - month_days(month, year); -- if (newdays < 0) -- break; -- days = newdays; -- } -- tm->tm_mon = month; -- tm->tm_mday = days + 1; -- -- tm->tm_hour = time / 3600; -- time -= tm->tm_hour * 3600; -- tm->tm_min = time / 60; -- tm->tm_sec = time - tm->tm_min * 60; --} --EXPORT_SYMBOL(rtc_time_to_tm); -- --/* -- * Does the rtc_time represent a valid date/time? -- */ --int rtc_valid_tm(struct rtc_time *tm) --{ -- if (tm->tm_year < 70 || -- tm->tm_mon >= 12 || -- tm->tm_mday < 1 || -- tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) || -- tm->tm_hour >= 24 || -- tm->tm_min >= 60 || -- tm->tm_sec >= 60) -- return -EINVAL; -- -- return 0; --} --EXPORT_SYMBOL(rtc_valid_tm); -- --/* -- * Convert Gregorian date to seconds since 01-01-1970 00:00:00. -- */ --int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) --{ -- *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, -- tm->tm_hour, tm->tm_min, tm->tm_sec); -- -- return 0; --} --EXPORT_SYMBOL(rtc_tm_to_time); -- - /* - * Calculate the next alarm time given the requested alarm time mask - * and the current time. -@@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time - } - } - --static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) -+static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) - { - memset(tm, 0, sizeof(struct rtc_time)); - return ops->read_time(tm); - } - --static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) -+static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) - { - int ret; - -@@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rt - return ret; - } - --static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) -+static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) - { - int ret = -EINVAL; - if (ops->read_alarm) { -@@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct - return ret; - } - --static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) -+static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) - { - int ret = -EINVAL; - if (ops->set_alarm) -@@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode - - switch (cmd) { - case RTC_ALM_READ: -- ret = rtc_read_alarm(ops, &alrm); -+ ret = rtc_arm_read_alarm(ops, &alrm); - if (ret) - break; - ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); -@@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode - alrm.time.tm_wday = -1; - alrm.time.tm_yday = -1; - alrm.time.tm_isdst = -1; -- ret = rtc_set_alarm(ops, &alrm); -+ ret = rtc_arm_set_alarm(ops, &alrm); - break; - - case RTC_RD_TIME: -- ret = rtc_read_time(ops, &tm); -+ ret = rtc_arm_read_time(ops, &tm); - if (ret) - break; - ret = copy_to_user(uarg, &tm, sizeof(tm)); -@@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode - ret = -EFAULT; - break; - } -- ret = rtc_set_time(ops, &tm); -+ ret = rtc_arm_set_time(ops, &tm); - break; - - case RTC_EPOCH_SET: -@@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode - ret = -EFAULT; - break; - } -- ret = rtc_set_alarm(ops, &alrm); -+ ret = rtc_arm_set_alarm(ops, &alrm); - break; - - case RTC_WKALM_RD: -- ret = rtc_read_alarm(ops, &alrm); -+ ret = rtc_arm_read_alarm(ops, &alrm); - if (ret) - break; - ret = copy_to_user(uarg, &alrm, sizeof(alrm)); -@@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, cha - struct rtc_time tm; - char *p = page; - -- if (rtc_read_time(ops, &tm) == 0) { -+ if (rtc_arm_read_time(ops, &tm) == 0) { - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" -@@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, cha - rtc_epoch); - } - -- if (rtc_read_alarm(ops, &alrm) == 0) { -+ if (rtc_arm_read_alarm(ops, &alrm) == 0) { - p += sprintf(p, "alrm_time\t: "); - if ((unsigned int)alrm.time.tm_hour <= 24) - p += sprintf(p, "%02d:", alrm.time.tm_hour); ---- linux-ixp4xx.orig/include/asm-arm/rtc.h 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/rtc.h 2006-03-08 01:59:26.000000000 +0100 -@@ -25,9 +25,6 @@ struct rtc_ops { - int (*proc)(char *buf); - }; - --void rtc_time_to_tm(unsigned long, struct rtc_time *); --int rtc_tm_to_time(struct rtc_time *, unsigned long *); --int rtc_valid_tm(struct rtc_time *); - void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *); - void rtc_update(unsigned long, unsigned long); - int register_rtc(struct rtc_ops *); ---- linux-ixp4xx.orig/drivers/char/Kconfig 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/drivers/char/Kconfig 2006-03-08 01:59:26.000000000 +0100 -@@ -695,7 +695,7 @@ config NVRAM - - config RTC - tristate "Enhanced Real Time Clock Support" -- depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV -+ depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM - ---help--- - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you ---- linux-ixp4xx.orig/arch/arm/Kconfig 2006-03-08 01:59:18.000000000 +0100 -+++ linux-ixp4xx/arch/arm/Kconfig 2006-03-08 01:59:26.000000000 +0100 -@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration" - config ARM - bool - default y -+ select RTC_LIB - help - The ARM series is a line of low-power-consumption RISC chip designs - licensed by ARM Ltd and targeted at embedded applications and -@@ -819,6 +820,8 @@ source "drivers/usb/Kconfig" - - source "drivers/mmc/Kconfig" - -+source "drivers/rtc/Kconfig" -+ - endmenu - - source "fs/Kconfig" ---- linux-ixp4xx.orig/arch/arm/mach-integrator/time.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-integrator/time.c 2006-03-08 01:59:26.000000000 +0100 -@@ -40,13 +40,13 @@ static int integrator_set_rtc(void) - return 1; - } - --static int rtc_read_alarm(struct rtc_wkalrm *alrm) -+static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm) - { - rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); - return 0; - } - --static inline int rtc_set_alarm(struct rtc_wkalrm *alrm) -+static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) - { - unsigned long time; - int ret; -@@ -62,7 +62,7 @@ static inline int rtc_set_alarm(struct r - return ret; - } - --static int rtc_read_time(struct rtc_time *tm) -+static int integrator_rtc_read_time(struct rtc_time *tm) - { - rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); - return 0; -@@ -76,7 +76,7 @@ static int rtc_read_time(struct rtc_time - * edge of the 1Hz clock, we must write the time one second - * in advance. - */ --static inline int rtc_set_time(struct rtc_time *tm) -+static inline int integrator_rtc_set_time(struct rtc_time *tm) - { - unsigned long time; - int ret; -@@ -90,10 +90,10 @@ static inline int rtc_set_time(struct rt - - static struct rtc_ops rtc_ops = { - .owner = THIS_MODULE, -- .read_time = rtc_read_time, -- .set_time = rtc_set_time, -- .read_alarm = rtc_read_alarm, -- .set_alarm = rtc_set_alarm, -+ .read_time = integrator_rtc_read_time, -+ .set_time = integrator_rtc_set_time, -+ .read_alarm = integrator_rtc_read_alarm, -+ .set_alarm = integrator_rtc_set_alarm, - }; - - static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id, ---- linux-ixp4xx.orig/arch/mips/ddb5xxx/common/rtc_ds1386.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/ddb5xxx/common/rtc_ds1386.c 2006-03-08 01:59:26.000000000 +0100 -@@ -165,6 +165,6 @@ rtc_ds1386_init(unsigned long base) - WRITE_RTC(0xB, byte); - - /* set the function pointers */ -- rtc_get_time = rtc_ds1386_get_time; -- rtc_set_time = rtc_ds1386_set_time; -+ rtc_mips_get_time = rtc_ds1386_get_time; -+ rtc_mips_set_time = rtc_ds1386_set_time; - } ---- linux-ixp4xx.orig/arch/mips/dec/time.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/dec/time.c 2006-03-08 01:59:26.000000000 +0100 -@@ -193,8 +193,8 @@ static void dec_ioasic_hpt_init(unsigned - - void __init dec_time_init(void) - { -- rtc_get_time = dec_rtc_get_time; -- rtc_set_mmss = dec_rtc_set_mmss; -+ rtc_mips_get_time = dec_rtc_get_time; -+ rtc_mips_set_mmss = dec_rtc_set_mmss; - - mips_timer_state = dec_timer_state; - mips_timer_ack = dec_timer_ack; ---- linux-ixp4xx.orig/arch/mips/ite-boards/generic/time.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/ite-boards/generic/time.c 2006-03-08 01:59:26.000000000 +0100 -@@ -227,8 +227,8 @@ void __init it8172_time_init(void) - - local_irq_restore(flags); - -- rtc_get_time = it8172_rtc_get_time; -- rtc_set_time = it8172_rtc_set_time; -+ rtc_mips_get_time = it8172_rtc_get_time; -+ rtc_mips_set_time = it8172_rtc_set_time; - } - - #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) ---- linux-ixp4xx.orig/arch/mips/jmr3927/common/rtc_ds1742.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/jmr3927/common/rtc_ds1742.c 2006-03-08 01:59:26.000000000 +0100 -@@ -159,8 +159,8 @@ rtc_ds1742_init(unsigned long base) - db_assert((rtc_base & 0xe0000000) == KSEG1); - - /* set the function pointers */ -- rtc_get_time = rtc_ds1742_get_time; -- rtc_set_time = rtc_ds1742_set_time; -+ rtc_mips_get_time = rtc_ds1742_get_time; -+ rtc_mips_set_time = rtc_ds1742_set_time; - - /* clear oscillator stop bit */ - CMOS_WRITE(RTC_READ, RTC_CONTROL); ---- linux-ixp4xx.orig/arch/mips/kernel/time.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/kernel/time.c 2006-03-08 01:59:26.000000000 +0100 -@@ -65,9 +65,9 @@ static int null_rtc_set_time(unsigned lo - return 0; - } - --unsigned long (*rtc_get_time)(void) = null_rtc_get_time; --int (*rtc_set_time)(unsigned long) = null_rtc_set_time; --int (*rtc_set_mmss)(unsigned long); -+unsigned long (*rtc_mips_get_time)(void) = null_rtc_get_time; -+int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time; -+int (*rtc_mips_set_mmss)(unsigned long); - - - /* usecs per counter cycle, shifted to left by 32 bits */ -@@ -438,7 +438,7 @@ irqreturn_t timer_interrupt(int irq, voi - - /* - * If we have an externally synchronized Linux clock, then update -- * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be -+ * CMOS clock accordingly every ~11 minutes. rtc_mips_set_time() has to be - * called as close as possible to 500 ms before the new second starts. - */ - write_seqlock(&xtime_lock); -@@ -446,7 +446,7 @@ irqreturn_t timer_interrupt(int irq, voi - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { -- if (rtc_set_mmss(xtime.tv_sec) == 0) { -+ if (rtc_mips_set_mmss(xtime.tv_sec) == 0) { - last_rtc_update = xtime.tv_sec; - } else { - /* do it again in 60 s */ -@@ -563,7 +563,7 @@ asmlinkage void ll_local_timer_interrupt - * b) (optional) calibrate and set the mips_hpt_frequency - * (only needed if you intended to use fixed_rate_gettimeoffset - * or use cpu counter as timer interrupt source) -- * 2) setup xtime based on rtc_get_time(). -+ * 2) setup xtime based on rtc_mips_get_time(). - * 3) choose a appropriate gettimeoffset routine. - * 4) calculate a couple of cached variables for later usage - * 5) board_timer_setup() - -@@ -631,10 +631,10 @@ void __init time_init(void) - if (board_time_init) - board_time_init(); - -- if (!rtc_set_mmss) -- rtc_set_mmss = rtc_set_time; -+ if (!rtc_mips_set_mmss) -+ rtc_mips_set_mmss = rtc_mips_set_time; - -- xtime.tv_sec = rtc_get_time(); -+ xtime.tv_sec = rtc_mips_get_time(); - xtime.tv_nsec = 0; - - set_normalized_timespec(&wall_to_monotonic, -@@ -770,8 +770,8 @@ void to_tm(unsigned long tim, struct rtc - - EXPORT_SYMBOL(rtc_lock); - EXPORT_SYMBOL(to_tm); --EXPORT_SYMBOL(rtc_set_time); --EXPORT_SYMBOL(rtc_get_time); -+EXPORT_SYMBOL(rtc_mips_set_time); -+EXPORT_SYMBOL(rtc_mips_get_time); - - unsigned long long sched_clock(void) - { ---- linux-ixp4xx.orig/arch/mips/lasat/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/lasat/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -174,8 +174,8 @@ void __init plat_setup(void) - - #ifdef CONFIG_DS1603 - ds1603 = &ds_defs[mips_machtype]; -- rtc_get_time = ds1603_read; -- rtc_set_time = ds1603_set; -+ rtc_mips_get_time = ds1603_read; -+ rtc_mips_set_time = ds1603_set; - #endif - - #ifdef DYNAMIC_SERIAL_INIT ---- linux-ixp4xx.orig/arch/mips/mips-boards/atlas/atlas_setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/mips-boards/atlas/atlas_setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -65,7 +65,7 @@ void __init plat_setup(void) - - board_time_init = mips_time_init; - board_timer_setup = mips_timer_setup; -- rtc_get_time = mips_rtc_get_time; -+ rtc_mips_get_time = mips_rtc_get_time; - } - - static void __init serial_init(void) ---- linux-ixp4xx.orig/arch/mips/mips-boards/malta/malta_setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/mips-boards/malta/malta_setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -225,5 +225,5 @@ void __init plat_setup(void) - - board_time_init = mips_time_init; - board_timer_setup = mips_timer_setup; -- rtc_get_time = mips_rtc_get_time; -+ rtc_mips_get_time = mips_rtc_get_time; - } ---- linux-ixp4xx.orig/arch/mips/momentum/jaguar_atx/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/momentum/jaguar_atx/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -228,8 +228,8 @@ void momenco_time_init(void) - mips_hpt_frequency = cpu_clock / 2; - board_timer_setup = momenco_timer_setup; - -- rtc_get_time = m48t37y_get_time; -- rtc_set_time = m48t37y_set_time; -+ rtc_mips_get_time = m48t37y_get_time; -+ rtc_mips_set_time = m48t37y_set_time; - } - - static struct resource mv_pci_io_mem0_resource = { ---- linux-ixp4xx.orig/arch/mips/momentum/ocelot_3/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/momentum/ocelot_3/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -215,8 +215,8 @@ void momenco_time_init(void) - mips_hpt_frequency = cpu_clock / 2; - board_timer_setup = momenco_timer_setup; - -- rtc_get_time = m48t37y_get_time; -- rtc_set_time = m48t37y_set_time; -+ rtc_mips_get_time = m48t37y_get_time; -+ rtc_mips_set_time = m48t37y_set_time; - } - - /* ---- linux-ixp4xx.orig/arch/mips/momentum/ocelot_c/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/momentum/ocelot_c/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -226,8 +226,8 @@ void momenco_time_init(void) - printk("momenco_time_init cpu_clock=%d\n", cpu_clock); - board_timer_setup = momenco_timer_setup; - -- rtc_get_time = m48t37y_get_time; -- rtc_set_time = m48t37y_set_time; -+ rtc_mips_get_time = m48t37y_get_time; -+ rtc_mips_set_time = m48t37y_set_time; - } - - void __init plat_setup(void) ---- linux-ixp4xx.orig/arch/mips/pmc-sierra/yosemite/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/pmc-sierra/yosemite/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -198,8 +198,8 @@ static void __init py_rtc_setup(void) - if (!m48t37_base) - printk(KERN_ERR "Mapping the RTC failed\n"); - -- rtc_get_time = m48t37y_get_time; -- rtc_set_time = m48t37y_set_time; -+ rtc_mips_get_time = m48t37y_get_time; -+ rtc_mips_set_time = m48t37y_set_time; - - write_seqlock(&xtime_lock); - xtime.tv_sec = m48t37y_get_time(); ---- linux-ixp4xx.orig/arch/mips/sgi-ip22/ip22-time.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/sgi-ip22/ip22-time.c 2006-03-08 01:59:26.000000000 +0100 -@@ -212,8 +212,8 @@ static void indy_timer_setup(struct irqa - void __init ip22_time_init(void) - { - /* setup hookup functions */ -- rtc_get_time = indy_rtc_get_time; -- rtc_set_time = indy_rtc_set_time; -+ rtc_mips_get_time = indy_rtc_get_time; -+ rtc_mips_set_time = indy_rtc_set_time; - - board_time_init = indy_time_init; - board_timer_setup = indy_timer_setup; ---- linux-ixp4xx.orig/arch/mips/sgi-ip32/ip32-setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/sgi-ip32/ip32-setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -91,8 +91,8 @@ void __init plat_setup(void) - { - board_be_init = ip32_be_init; - -- rtc_get_time = mc146818_get_cmos_time; -- rtc_set_mmss = mc146818_set_rtc_mmss; -+ rtc_mips_get_time = mc146818_get_cmos_time; -+ rtc_mips_set_mmss = mc146818_set_rtc_mmss; - - board_time_init = ip32_time_init; - board_timer_setup = ip32_timer_setup; ---- linux-ixp4xx.orig/arch/mips/sibyte/swarm/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/sibyte/swarm/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -114,14 +114,14 @@ void __init plat_setup(void) - - if (xicor_probe()) { - printk("swarm setup: Xicor 1241 RTC detected.\n"); -- rtc_get_time = xicor_get_time; -- rtc_set_time = xicor_set_time; -+ rtc_mips_get_time = xicor_get_time; -+ rtc_mips_set_time = xicor_set_time; - } - - if (m41t81_probe()) { - printk("swarm setup: M41T81 RTC detected.\n"); -- rtc_get_time = m41t81_get_time; -- rtc_set_time = m41t81_set_time; -+ rtc_mips_get_time = m41t81_get_time; -+ rtc_mips_set_time = m41t81_set_time; - } - - printk("This kernel optimized for " ---- linux-ixp4xx.orig/arch/mips/sni/setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/sni/setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -164,8 +164,8 @@ static struct pci_controller sni_control - - static inline void sni_pcimt_time_init(void) - { -- rtc_get_time = mc146818_get_cmos_time; -- rtc_set_time = mc146818_set_rtc_mmss; -+ rtc_mips_get_time = mc146818_get_cmos_time; -+ rtc_mips_set_time = mc146818_set_rtc_mmss; - } - - void __init plat_setup(void) ---- linux-ixp4xx.orig/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c 2006-03-08 01:59:26.000000000 +0100 -@@ -1036,8 +1036,8 @@ toshiba_rbtx4927_time_init(void) - - #ifdef CONFIG_RTC_DS1742 - -- rtc_get_time = rtc_ds1742_get_time; -- rtc_set_time = rtc_ds1742_set_time; -+ rtc_mips_get_time = rtc_ds1742_get_time; -+ rtc_mips_set_time = rtc_ds1742_set_time; - - TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, - ":rtc_ds1742_init()-\n"); ---- linux-ixp4xx.orig/arch/mips/tx4938/common/rtc_rx5c348.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/mips/tx4938/common/rtc_rx5c348.c 2006-03-08 01:59:26.000000000 +0100 -@@ -197,6 +197,6 @@ rtc_rx5c348_init(int chipid) - srtc_24h = 1; - - /* set the function pointers */ -- rtc_get_time = rtc_rx5c348_get_time; -- rtc_set_time = rtc_rx5c348_set_time; -+ rtc_mips_get_time = rtc_rx5c348_get_time; -+ rtc_mips_set_time = rtc_rx5c348_set_time; - } ---- linux-ixp4xx.orig/include/asm-mips/time.h 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/include/asm-mips/time.h 2006-03-08 01:59:26.000000000 +0100 -@@ -26,14 +26,14 @@ extern spinlock_t rtc_lock; - - /* - * RTC ops. By default, they point to no-RTC functions. -- * rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds. -- * rtc_set_time - reverse the above translation and set time to RTC. -- * rtc_set_mmss - similar to rtc_set_time, but only min and sec need -+ * rtc_mips_get_time - mktime(year, mon, day, hour, min, sec) in seconds. -+ * rtc_mips_set_time - reverse the above translation and set time to RTC. -+ * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need - * to be set. Used by RTC sync-up. - */ --extern unsigned long (*rtc_get_time)(void); --extern int (*rtc_set_time)(unsigned long); --extern int (*rtc_set_mmss)(unsigned long); -+extern unsigned long (*rtc_mips_get_time)(void); -+extern int (*rtc_mips_set_time)(unsigned long); -+extern int (*rtc_mips_set_mmss)(unsigned long); - - /* - * Timer interrupt functions. ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/class.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,145 @@ -+/* -+ * RTC subsystem, base class -+ * -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * class skeleton from drivers/hwmon/hwmon.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+#include <linux/kdev_t.h> -+#include <linux/idr.h> -+ -+static DEFINE_IDR(rtc_idr); -+static DEFINE_MUTEX(idr_lock); -+struct class *rtc_class; -+ -+static void rtc_device_release(struct class_device *class_dev) -+{ -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ mutex_lock(&idr_lock); -+ idr_remove(&rtc_idr, rtc->id); -+ mutex_unlock(&idr_lock); -+ kfree(rtc); -+} -+ -+/** -+ * rtc_device_register - register w/ RTC class -+ * @dev: the device to register -+ * -+ * rtc_device_unregister() must be called when the class device is no -+ * longer needed. -+ * -+ * Returns the pointer to the new struct class device. -+ */ -+struct rtc_device *rtc_device_register(const char *name, struct device *dev, -+ struct rtc_class_ops *ops, -+ struct module *owner) -+{ -+ struct rtc_device *rtc; -+ int id, err; -+ -+ if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ -+ mutex_lock(&idr_lock); -+ err = idr_get_new(&rtc_idr, NULL, &id); -+ mutex_unlock(&idr_lock); -+ -+ if (err < 0) -+ goto exit; -+ -+ id = id & MAX_ID_MASK; -+ -+ rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); -+ if (rtc == NULL) { -+ err = -ENOMEM; -+ goto exit_idr; -+ } -+ -+ rtc->id = id; -+ rtc->ops = ops; -+ rtc->owner = owner; -+ rtc->class_dev.dev = dev; -+ rtc->class_dev.class = rtc_class; -+ rtc->class_dev.release = rtc_device_release; -+ -+ mutex_init(&rtc->ops_lock); -+ spin_lock_init(&rtc->irq_lock); -+ spin_lock_init(&rtc->irq_task_lock); -+ -+ strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); -+ snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id); -+ -+ err = class_device_register(&rtc->class_dev); -+ if (err) -+ goto exit_kfree; -+ -+ dev_info(dev, "rtc core: registered %s as %s\n", -+ rtc->name, rtc->class_dev.class_id); -+ -+ return rtc; -+ -+exit_kfree: -+ kfree(rtc); -+ -+exit_idr: -+ idr_remove(&rtc_idr, id); -+ -+exit: -+ return ERR_PTR(err); -+} -+EXPORT_SYMBOL_GPL(rtc_device_register); -+ -+ -+/** -+ * rtc_device_unregister - removes the previously registered RTC class device -+ * -+ * @rtc: the RTC class device to destroy -+ */ -+void rtc_device_unregister(struct rtc_device *rtc) -+{ -+ mutex_lock(&rtc->ops_lock); -+ rtc->ops = NULL; -+ mutex_unlock(&rtc->ops_lock); -+ class_device_unregister(&rtc->class_dev); -+} -+EXPORT_SYMBOL_GPL(rtc_device_unregister); -+ -+int rtc_interface_register(struct class_interface *intf) -+{ -+ intf->class = rtc_class; -+ return class_interface_register(intf); -+} -+EXPORT_SYMBOL_GPL(rtc_interface_register); -+ -+static int __init rtc_init(void) -+{ -+ rtc_class = class_create(THIS_MODULE, "rtc"); -+ if (IS_ERR(rtc_class)) { -+ printk(KERN_ERR "%s: couldn't create class\n", __FILE__); -+ return PTR_ERR(rtc_class); -+ } -+ return 0; -+} -+ -+static void __exit rtc_exit(void) -+{ -+ class_destroy(rtc_class); -+} -+ -+module_init(rtc_init); -+module_exit(rtc_exit); -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>"); -+MODULE_DESCRIPTION("RTC class support"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/interface.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,277 @@ -+/* -+ * RTC subsystem, interface functions -+ * -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on arch/arm/common/rtctime.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/rtc.h> -+ -+int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) -+{ -+ int err; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ err = mutex_lock_interruptible(&rtc->ops_lock); -+ if (err) -+ return -EBUSY; -+ -+ if (!rtc->ops) -+ err = -ENODEV; -+ else if (!rtc->ops->read_time) -+ err = -EINVAL; -+ else { -+ memset(tm, 0, sizeof(struct rtc_time)); -+ err = rtc->ops->read_time(class_dev->dev, tm); -+ } -+ -+ mutex_unlock(&rtc->ops_lock); -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_read_time); -+ -+int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) -+{ -+ int err; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ err = rtc_valid_tm(tm); -+ if (err != 0) -+ return err; -+ -+ err = mutex_lock_interruptible(&rtc->ops_lock); -+ if (err) -+ return -EBUSY; -+ -+ if (!rtc->ops) -+ err = -ENODEV; -+ else if (!rtc->ops->set_time) -+ err = -EINVAL; -+ else -+ err = rtc->ops->set_time(class_dev->dev, tm); -+ -+ mutex_unlock(&rtc->ops_lock); -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_set_time); -+ -+int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) -+{ -+ int err; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ err = mutex_lock_interruptible(&rtc->ops_lock); -+ if (err) -+ return -EBUSY; -+ -+ if (!rtc->ops) -+ err = -ENODEV; -+ else if (rtc->ops->set_mmss) -+ err = rtc->ops->set_mmss(class_dev->dev, secs); -+ else if (rtc->ops->read_time && rtc->ops->set_time) { -+ struct rtc_time new, old; -+ -+ err = rtc->ops->read_time(class_dev->dev, &old); -+ if (err == 0) { -+ rtc_time_to_tm(secs, &new); -+ -+ /* -+ * avoid writing when we're going to change the day of -+ * the month. We will retry in the next minute. This -+ * basically means that if the RTC must not drift -+ * by more than 1 minute in 11 minutes. -+ */ -+ if (!((old.tm_hour == 23 && old.tm_min == 59) || -+ (new.tm_hour == 23 && new.tm_min == 59))) -+ err = rtc->ops->set_time(class_dev->dev, &new); -+ } -+ } -+ else -+ err = -EINVAL; -+ -+ mutex_unlock(&rtc->ops_lock); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_set_mmss); -+ -+int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) -+{ -+ int err; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ err = mutex_lock_interruptible(&rtc->ops_lock); -+ if (err) -+ return -EBUSY; -+ -+ if (rtc->ops == NULL) -+ err = -ENODEV; -+ else if (!rtc->ops->read_alarm) -+ err = -EINVAL; -+ else { -+ memset(alarm, 0, sizeof(struct rtc_wkalrm)); -+ err = rtc->ops->read_alarm(class_dev->dev, alarm); -+ } -+ -+ mutex_unlock(&rtc->ops_lock); -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_read_alarm); -+ -+int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) -+{ -+ int err; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ err = mutex_lock_interruptible(&rtc->ops_lock); -+ if (err) -+ return -EBUSY; -+ -+ if (!rtc->ops) -+ err = -ENODEV; -+ else if (!rtc->ops->set_alarm) -+ err = -EINVAL; -+ else -+ err = rtc->ops->set_alarm(class_dev->dev, alarm); -+ -+ mutex_unlock(&rtc->ops_lock); -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_set_alarm); -+ -+void rtc_update_irq(struct class_device *class_dev, -+ unsigned long num, unsigned long events) -+{ -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ spin_lock(&rtc->irq_lock); -+ rtc->irq_data = (rtc->irq_data + (num << 8)) | events; -+ spin_unlock(&rtc->irq_lock); -+ -+ spin_lock(&rtc->irq_task_lock); -+ if (rtc->irq_task) -+ rtc->irq_task->func(rtc->irq_task->private_data); -+ spin_unlock(&rtc->irq_task_lock); -+ -+ wake_up_interruptible(&rtc->irq_queue); -+ kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); -+} -+EXPORT_SYMBOL_GPL(rtc_update_irq); -+ -+struct class_device *rtc_class_open(char *name) -+{ -+ struct class_device *class_dev = NULL, -+ *class_dev_tmp; -+ -+ down(&rtc_class->sem); -+ list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { -+ if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { -+ class_dev = class_dev_tmp; -+ break; -+ } -+ } -+ -+ if (class_dev) { -+ if (!try_module_get(to_rtc_device(class_dev)->owner)) -+ class_dev = NULL; -+ } -+ up(&rtc_class->sem); -+ -+ return class_dev; -+} -+EXPORT_SYMBOL_GPL(rtc_class_open); -+ -+void rtc_class_close(struct class_device *class_dev) -+{ -+ module_put(to_rtc_device(class_dev)->owner); -+} -+EXPORT_SYMBOL_GPL(rtc_class_close); -+ -+int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) -+{ -+ int retval = -EBUSY; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ if (task == NULL || task->func == NULL) -+ return -EINVAL; -+ -+ spin_lock(&rtc->irq_task_lock); -+ if (rtc->irq_task == NULL) { -+ rtc->irq_task = task; -+ retval = 0; -+ } -+ spin_unlock(&rtc->irq_task_lock); -+ -+ return retval; -+} -+EXPORT_SYMBOL_GPL(rtc_irq_register); -+ -+void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) -+{ -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ spin_lock(&rtc->irq_task_lock); -+ if (rtc->irq_task == task) -+ rtc->irq_task = NULL; -+ spin_unlock(&rtc->irq_task_lock); -+} -+EXPORT_SYMBOL_GPL(rtc_irq_unregister); -+ -+int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled) -+{ -+ int err = 0; -+ unsigned long flags; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ spin_lock_irqsave(&rtc->irq_task_lock, flags); -+ if (rtc->irq_task != task) -+ err = -ENXIO; -+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags); -+ -+ if (err == 0) -+ err = rtc->ops->irq_set_state(class_dev->dev, enabled); -+ -+ return err; -+} -+EXPORT_SYMBOL_GPL(rtc_irq_set_state); -+ -+int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) -+{ -+ int err = 0, tmp = 0; -+ unsigned long flags; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ /* allowed range is 2-8192 */ -+ if (freq < 2 || freq > 8192) -+ return -EINVAL; -+/* -+ FIXME: this does not belong here, will move where appropriate -+ at a later stage. It cannot hurt right now, trust me :) -+ if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) -+ return -EACCES; -+*/ -+ /* check if freq is a power of 2 */ -+ while (freq > (1 << tmp)) -+ tmp++; -+ -+ if (freq != (1 << tmp)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&rtc->irq_task_lock, flags); -+ if (rtc->irq_task != task) -+ err = -ENXIO; -+ spin_unlock_irqrestore(&rtc->irq_task_lock, flags); -+ -+ if (err == 0) { -+ err = rtc->ops->irq_set_freq(class_dev->dev, freq); -+ if (err == 0) -+ rtc->irq_freq = freq; -+ } -+ return err; -+} ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/hctosys.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,69 @@ -+/* -+ * RTC subsystem, initialize system time on startup -+ * -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/rtc.h> -+ -+/* IMPORTANT: the RTC only stores whole seconds. It is arbitrary -+ * whether it stores the most close value or the value with partial -+ * seconds truncated. However, it is important that we use it to store -+ * the truncated value. This is because otherwise it is necessary, -+ * in an rtc sync function, to read both xtime.tv_sec and -+ * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read -+ * of >32bits is not possible. So storing the most close value would -+ * slow down the sync API. So here we have the truncated value and -+ * the best guess is to add 0.5s. -+ */ -+ -+static int __init rtc_hctosys(void) -+{ -+ int err; -+ struct rtc_time tm; -+ struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); -+ -+ if (class_dev == NULL) { -+ printk("%s: unable to open rtc device (%s)\n", -+ __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); -+ return -ENODEV; -+ } -+ -+ err = rtc_read_time(class_dev, &tm); -+ if (err == 0) { -+ err = rtc_valid_tm(&tm); -+ if (err == 0) { -+ struct timespec tv; -+ -+ tv.tv_nsec = NSEC_PER_SEC >> 1; -+ -+ rtc_tm_to_time(&tm, &tv.tv_sec); -+ -+ do_settimeofday(&tv); -+ -+ dev_info(class_dev->dev, -+ "setting the system clock to " -+ "%d-%02d-%02d %02d:%02d:%02d (%u)\n", -+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, -+ tm.tm_hour, tm.tm_min, tm.tm_sec, -+ (unsigned int) tv.tv_sec); -+ } -+ else -+ dev_err(class_dev->dev, -+ "hctosys: invalid date/time\n"); -+ } -+ else -+ dev_err(class_dev->dev, -+ "hctosys: unable to read the hardware clock\n"); -+ -+ rtc_class_close(class_dev); -+ -+ return 0; -+} -+ -+late_initcall(rtc_hctosys); ---- linux-ixp4xx.orig/CREDITS 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/CREDITS 2006-03-08 01:59:26.000000000 +0100 -@@ -3741,10 +3741,11 @@ D: Mylex DAC960 PCI RAID driver - D: Miscellaneous kernel fixes - - N: Alessandro Zummo --E: azummo@ita.flashnet.it --W: http://freepage.logicom.it/azummo/ -+E: a.zummo@towertech.it - D: CMI8330 support is sb_card.c - D: ISAPnP fixes in sb_card.c -+D: ZyXEL omni.net lcd plus driver -+D: RTC subsystem - S: Italy - - N: Marc Zyngier ---- linux-ixp4xx.orig/MAINTAINERS 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/MAINTAINERS 2006-03-08 01:59:26.000000000 +0100 -@@ -2193,6 +2193,12 @@ M: p_gortmaker@yahoo.com - L: linux-kernel@vger.kernel.org - S: Maintained - -+REAL TIME CLOCK (RTC) SUBSYSTEM -+P: Alessandro Zummo -+M: a.zummo@towertech.it -+L: linux-kernel@vger.kernel.org -+S: Maintained -+ - REISERFS FILE SYSTEM - P: Hans Reiser - M: reiserfs-dev@namesys.com ---- linux-ixp4xx.orig/drivers/i2c/chips/x1205.c 2006-03-08 01:59:09.000000000 +0100 -+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 -@@ -1,698 +0,0 @@ --/* -- * x1205.c - An i2c driver for the Xicor X1205 RTC -- * Copyright 2004 Karen Spearel -- * Copyright 2005 Alessandro Zummo -- * -- * please send all reports to: -- * kas11 at tampabay dot rr dot com -- * a dot zummo at towertech dot it -- * -- * based on the other drivers in this same directory. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- */ -- --#include <linux/module.h> --#include <linux/init.h> --#include <linux/slab.h> --#include <linux/i2c.h> --#include <linux/string.h> --#include <linux/bcd.h> --#include <linux/rtc.h> --#include <linux/list.h> -- --#include <linux/x1205.h> -- --#define DRV_VERSION "0.9.9" -- --/* Addresses to scan: none. This chip is located at -- * 0x6f and uses a two bytes register addressing. -- * Two bytes need to be written to read a single register, -- * while most other chips just require one and take the second -- * one as the data to be written. To prevent corrupting -- * unknown chips, the user must explicitely set the probe parameter. -- */ -- --static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -- --/* Insmod parameters */ --I2C_CLIENT_INSMOD; --I2C_CLIENT_MODULE_PARM(hctosys, -- "Set the system time from the hardware clock upon initialization"); -- --/* offsets into CCR area */ -- --#define CCR_SEC 0 --#define CCR_MIN 1 --#define CCR_HOUR 2 --#define CCR_MDAY 3 --#define CCR_MONTH 4 --#define CCR_YEAR 5 --#define CCR_WDAY 6 --#define CCR_Y2K 7 -- --#define X1205_REG_SR 0x3F /* status register */ --#define X1205_REG_Y2K 0x37 --#define X1205_REG_DW 0x36 --#define X1205_REG_YR 0x35 --#define X1205_REG_MO 0x34 --#define X1205_REG_DT 0x33 --#define X1205_REG_HR 0x32 --#define X1205_REG_MN 0x31 --#define X1205_REG_SC 0x30 --#define X1205_REG_DTR 0x13 --#define X1205_REG_ATR 0x12 --#define X1205_REG_INT 0x11 --#define X1205_REG_0 0x10 --#define X1205_REG_Y2K1 0x0F --#define X1205_REG_DWA1 0x0E --#define X1205_REG_YRA1 0x0D --#define X1205_REG_MOA1 0x0C --#define X1205_REG_DTA1 0x0B --#define X1205_REG_HRA1 0x0A --#define X1205_REG_MNA1 0x09 --#define X1205_REG_SCA1 0x08 --#define X1205_REG_Y2K0 0x07 --#define X1205_REG_DWA0 0x06 --#define X1205_REG_YRA0 0x05 --#define X1205_REG_MOA0 0x04 --#define X1205_REG_DTA0 0x03 --#define X1205_REG_HRA0 0x02 --#define X1205_REG_MNA0 0x01 --#define X1205_REG_SCA0 0x00 -- --#define X1205_CCR_BASE 0x30 /* Base address of CCR */ --#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ -- --#define X1205_SR_RTCF 0x01 /* Clock failure */ --#define X1205_SR_WEL 0x02 /* Write Enable Latch */ --#define X1205_SR_RWEL 0x04 /* Register Write Enable */ -- --#define X1205_DTR_DTR0 0x01 --#define X1205_DTR_DTR1 0x02 --#define X1205_DTR_DTR2 0x04 -- --#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ -- --/* Prototypes */ --static int x1205_attach(struct i2c_adapter *adapter); --static int x1205_detach(struct i2c_client *client); --static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); --static int x1205_command(struct i2c_client *client, unsigned int cmd, -- void *arg); -- --static struct i2c_driver x1205_driver = { -- .driver = { -- .name = "x1205", -- }, -- .attach_adapter = &x1205_attach, -- .detach_client = &x1205_detach, --}; -- --struct x1205_data { -- struct i2c_client client; -- struct list_head list; -- unsigned int epoch; --}; -- --static const unsigned char days_in_mo[] = -- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -- --static LIST_HEAD(x1205_clients); -- --/* Workaround until the I2C subsytem will allow to send -- * commands to a specific client. This function will send the command -- * to the first client. -- */ --int x1205_do_command(unsigned int cmd, void *arg) --{ -- struct list_head *walk; -- struct list_head *tmp; -- struct x1205_data *data; -- -- list_for_each_safe(walk, tmp, &x1205_clients) { -- data = list_entry(walk, struct x1205_data, list); -- return x1205_command(&data->client, cmd, arg); -- } -- -- return -ENODEV; --} -- --#define is_leap(year) \ -- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) -- --/* make sure the rtc_time values are in bounds */ --static int x1205_validate_tm(struct rtc_time *tm) --{ -- int year = tm->tm_year + 1900; -- -- if ((tm->tm_year < 70) || (tm->tm_year > 255)) -- return -EINVAL; -- -- if ((tm->tm_mon > 11) || (tm->tm_mday == 0)) -- return -EINVAL; -- -- if (tm->tm_mday > days_in_mo[tm->tm_mon] -- + ((tm->tm_mon == 1) && is_leap(year))) -- return -EINVAL; -- -- if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60)) -- return -EINVAL; -- -- return 0; --} -- --/* -- * In the routines that deal directly with the x1205 hardware, we use -- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch -- * Epoch is initialized as 2000. Time is set to UTC. -- */ --static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, -- u8 reg_base) --{ -- unsigned char dt_addr[2] = { 0, reg_base }; -- static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; -- -- unsigned char buf[8], sr; -- -- struct i2c_msg msgs[] = { -- { client->addr, 0, 2, sr_addr }, /* setup read ptr */ -- { client->addr, I2C_M_RD, 1, &sr }, /* read status */ -- { client->addr, 0, 2, dt_addr }, /* setup read ptr */ -- { client->addr, I2C_M_RD, 8, buf }, /* read date */ -- }; -- -- struct x1205_data *data = i2c_get_clientdata(client); -- -- /* read status register */ -- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -- return -EIO; -- } -- -- /* check for battery failure */ -- if (sr & X1205_SR_RTCF) { -- dev_warn(&client->dev, -- "Clock had a power failure, you must set the date.\n"); -- return -EINVAL; -- } -- -- /* read date registers */ -- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) { -- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -- return -EIO; -- } -- -- dev_dbg(&client->dev, -- "%s: raw read data - sec=%02x, min=%02x, hr=%02x, " -- "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", -- __FUNCTION__, -- buf[0], buf[1], buf[2], buf[3], -- buf[4], buf[5], buf[6], buf[7]); -- -- tm->tm_sec = BCD2BIN(buf[CCR_SEC]); -- tm->tm_min = BCD2BIN(buf[CCR_MIN]); -- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ -- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); -- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); -- data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100; -- tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900; -- tm->tm_wday = buf[CCR_WDAY]; -- -- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " -- "mday=%d, mon=%d, year=%d, wday=%d\n", -- __FUNCTION__, -- tm->tm_sec, tm->tm_min, tm->tm_hour, -- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -- -- return 0; --} -- --static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, -- int datetoo, u8 reg_base) --{ -- int i, err, xfer; -- -- unsigned char buf[8]; -- -- static const unsigned char wel[3] = { 0, X1205_REG_SR, -- X1205_SR_WEL }; -- -- static const unsigned char rwel[3] = { 0, X1205_REG_SR, -- X1205_SR_WEL | X1205_SR_RWEL }; -- -- static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; -- -- struct x1205_data *data = i2c_get_clientdata(client); -- -- /* check if all values in the tm struct are correct */ -- if ((err = x1205_validate_tm(tm)) < 0) -- return err; -- -- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " -- "mday=%d, mon=%d, year=%d, wday=%d\n", -- __FUNCTION__, -- tm->tm_sec, tm->tm_min, tm->tm_hour, -- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -- -- buf[CCR_SEC] = BIN2BCD(tm->tm_sec); -- buf[CCR_MIN] = BIN2BCD(tm->tm_min); -- -- /* set hour and 24hr bit */ -- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; -- -- /* should we also set the date? */ -- if (datetoo) { -- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); -- -- /* month, 0 - 11 */ -- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); -- -- /* year, since 1900 */ -- buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch); -- buf[CCR_WDAY] = tm->tm_wday & 0x07; -- buf[CCR_Y2K] = BIN2BCD(data->epoch / 100); -- } -- -- /* this sequence is required to unlock the chip */ -- xfer = i2c_master_send(client, wel, 3); -- if (xfer != 3) { -- dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); -- return -EIO; -- } -- -- xfer = i2c_master_send(client, rwel, 3); -- if (xfer != 3) { -- dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); -- return -EIO; -- } -- -- /* write register's data */ -- for (i = 0; i < (datetoo ? 8 : 3); i++) { -- unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; -- -- xfer = i2c_master_send(client, rdata, 3); -- if (xfer != 3) { -- dev_err(&client->dev, -- "%s: xfer=%d addr=%02x, data=%02x\n", -- __FUNCTION__, -- xfer, rdata[1], rdata[2]); -- return -EIO; -- } -- }; -- -- /* disable further writes */ -- xfer = i2c_master_send(client, diswe, 3); -- if (xfer != 3) { -- dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); -- return -EIO; -- } -- -- return 0; --} -- --static int x1205_get_dtrim(struct i2c_client *client, int *trim) --{ -- unsigned char dtr; -- static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; -- -- struct i2c_msg msgs[] = { -- { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ -- { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ -- }; -- -- /* read dtr register */ -- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -- return -EIO; -- } -- -- dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr); -- -- *trim = 0; -- -- if (dtr & X1205_DTR_DTR0) -- *trim += 20; -- -- if (dtr & X1205_DTR_DTR1) -- *trim += 10; -- -- if (dtr & X1205_DTR_DTR2) -- *trim = -*trim; -- -- return 0; --} -- --static int x1205_get_atrim(struct i2c_client *client, int *trim) --{ -- s8 atr; -- static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; -- -- struct i2c_msg msgs[] = { -- { client->addr, 0, 2, atr_addr }, /* setup read ptr */ -- { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ -- }; -- -- /* read atr register */ -- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -- return -EIO; -- } -- -- dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr); -- -- /* atr is a two's complement value on 6 bits, -- * perform sign extension. The formula is -- * Catr = (atr * 0.25pF) + 11.00pF. -- */ -- if (atr & 0x20) -- atr |= 0xC0; -- -- dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr); -- -- *trim = (atr * 250) + 11000; -- -- dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim); -- -- return 0; --} -- --static int x1205_hctosys(struct i2c_client *client) --{ -- int err; -- -- struct rtc_time tm; -- struct timespec tv; -- -- err = x1205_command(client, X1205_CMD_GETDATETIME, &tm); -- -- if (err) { -- dev_err(&client->dev, -- "Unable to set the system clock\n"); -- return err; -- } -- -- /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary -- * whether it stores the most close value or the value with partial -- * seconds truncated. However, it is important that we use it to store -- * the truncated value. This is because otherwise it is necessary, -- * in an rtc sync function, to read both xtime.tv_sec and -- * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read -- * of >32bits is not possible. So storing the most close value would -- * slow down the sync API. So here we have the truncated value and -- * the best guess is to add 0.5s. -- */ -- -- tv.tv_nsec = NSEC_PER_SEC >> 1; -- -- /* WARNING: this is not the C library 'mktime' call, it is a built in -- * inline function from include/linux/time.h. It expects (requires) -- * the month to be in the range 1-12 -- */ -- -- tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, -- tm.tm_mday, tm.tm_hour, -- tm.tm_min, tm.tm_sec); -- -- do_settimeofday(&tv); -- -- dev_info(&client->dev, -- "setting the system clock to %d-%d-%d %d:%d:%d\n", -- tm.tm_year + 1900, tm.tm_mon + 1, -- tm.tm_mday, tm.tm_hour, tm.tm_min, -- tm.tm_sec); -- -- return 0; --} -- --struct x1205_limit --{ -- unsigned char reg; -- unsigned char mask; -- unsigned char min; -- unsigned char max; --}; -- --static int x1205_validate_client(struct i2c_client *client) --{ -- int i, xfer; -- -- /* Probe array. We will read the register at the specified -- * address and check if the given bits are zero. -- */ -- static const unsigned char probe_zero_pattern[] = { -- /* register, mask */ -- X1205_REG_SR, 0x18, -- X1205_REG_DTR, 0xF8, -- X1205_REG_ATR, 0xC0, -- X1205_REG_INT, 0x18, -- X1205_REG_0, 0xFF, -- }; -- -- static const struct x1205_limit probe_limits_pattern[] = { -- /* register, mask, min, max */ -- { X1205_REG_Y2K, 0xFF, 19, 20 }, -- { X1205_REG_DW, 0xFF, 0, 6 }, -- { X1205_REG_YR, 0xFF, 0, 99 }, -- { X1205_REG_MO, 0xFF, 0, 12 }, -- { X1205_REG_DT, 0xFF, 0, 31 }, -- { X1205_REG_HR, 0x7F, 0, 23 }, -- { X1205_REG_MN, 0xFF, 0, 59 }, -- { X1205_REG_SC, 0xFF, 0, 59 }, -- { X1205_REG_Y2K1, 0xFF, 19, 20 }, -- { X1205_REG_Y2K0, 0xFF, 19, 20 }, -- }; -- -- /* check that registers have bits a 0 where expected */ -- for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) { -- unsigned char buf; -- -- unsigned char addr[2] = { 0, probe_zero_pattern[i] }; -- -- struct i2c_msg msgs[2] = { -- { client->addr, 0, 2, addr }, -- { client->addr, I2C_M_RD, 1, &buf }, -- }; -- -- xfer = i2c_transfer(client->adapter, msgs, 2); -- if (xfer != 2) { -- dev_err(&client->adapter->dev, -- "%s: could not read register %x\n", -- __FUNCTION__, addr[1]); -- -- return -EIO; -- } -- -- if ((buf & probe_zero_pattern[i+1]) != 0) { -- dev_err(&client->adapter->dev, -- "%s: register=%02x, zero pattern=%d, value=%x\n", -- __FUNCTION__, addr[1], i, buf); -- -- return -ENODEV; -- } -- } -- -- /* check limits (only registers with bcd values) */ -- for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) { -- unsigned char reg, value; -- -- unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; -- -- struct i2c_msg msgs[2] = { -- { client->addr, 0, 2, addr }, -- { client->addr, I2C_M_RD, 1, ® }, -- }; -- -- xfer = i2c_transfer(client->adapter, msgs, 2); -- -- if (xfer != 2) { -- dev_err(&client->adapter->dev, -- "%s: could not read register %x\n", -- __FUNCTION__, addr[1]); -- -- return -EIO; -- } -- -- value = BCD2BIN(reg & probe_limits_pattern[i].mask); -- -- if (value > probe_limits_pattern[i].max || -- value < probe_limits_pattern[i].min) { -- dev_dbg(&client->adapter->dev, -- "%s: register=%x, lim pattern=%d, value=%d\n", -- __FUNCTION__, addr[1], i, value); -- -- return -ENODEV; -- } -- } -- -- return 0; --} -- --static int x1205_attach(struct i2c_adapter *adapter) --{ -- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -- -- return i2c_probe(adapter, &addr_data, x1205_probe); --} -- --int x1205_direct_attach(int adapter_id, -- struct i2c_client_address_data *address_data) --{ -- int err; -- struct i2c_adapter *adapter = i2c_get_adapter(adapter_id); -- -- if (adapter) { -- err = i2c_probe(adapter, -- address_data, x1205_probe); -- -- i2c_put_adapter(adapter); -- -- return err; -- } -- -- return -ENODEV; --} -- --static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) --{ -- struct i2c_client *client; -- struct x1205_data *data; -- -- int err = 0; -- -- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -- -- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { -- err = -ENODEV; -- goto exit; -- } -- -- if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) { -- err = -ENOMEM; -- goto exit; -- } -- -- /* Initialize our structures */ -- data->epoch = 2000; -- -- client = &data->client; -- client->addr = address; -- client->driver = &x1205_driver; -- client->adapter = adapter; -- -- strlcpy(client->name, "x1205", I2C_NAME_SIZE); -- -- i2c_set_clientdata(client, data); -- -- /* Verify the chip is really an X1205 */ -- if (kind < 0) { -- if (x1205_validate_client(client) < 0) { -- err = -ENODEV; -- goto exit_kfree; -- } -- } -- -- /* Inform the i2c layer */ -- if ((err = i2c_attach_client(client))) -- goto exit_kfree; -- -- list_add(&data->list, &x1205_clients); -- -- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -- -- /* If requested, set the system time */ -- if (hctosys) -- x1205_hctosys(client); -- -- return 0; -- --exit_kfree: -- kfree(data); -- --exit: -- return err; --} -- --static int x1205_detach(struct i2c_client *client) --{ -- int err; -- struct x1205_data *data = i2c_get_clientdata(client); -- -- dev_dbg(&client->dev, "%s\n", __FUNCTION__); -- -- if ((err = i2c_detach_client(client))) -- return err; -- -- list_del(&data->list); -- -- kfree(data); -- -- return 0; --} -- --static int x1205_command(struct i2c_client *client, unsigned int cmd, -- void *param) --{ -- if (param == NULL) -- return -EINVAL; -- -- if (!capable(CAP_SYS_TIME)) -- return -EACCES; -- -- dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); -- -- switch (cmd) { -- case X1205_CMD_GETDATETIME: -- return x1205_get_datetime(client, param, X1205_CCR_BASE); -- -- case X1205_CMD_SETTIME: -- return x1205_set_datetime(client, param, 0, -- X1205_CCR_BASE); -- -- case X1205_CMD_SETDATETIME: -- return x1205_set_datetime(client, param, 1, -- X1205_CCR_BASE); -- -- case X1205_CMD_GETALARM: -- return x1205_get_datetime(client, param, X1205_ALM0_BASE); -- -- case X1205_CMD_SETALARM: -- return x1205_set_datetime(client, param, 1, -- X1205_ALM0_BASE); -- -- case X1205_CMD_GETDTRIM: -- return x1205_get_dtrim(client, param); -- -- case X1205_CMD_GETATRIM: -- return x1205_get_atrim(client, param); -- -- default: -- return -EINVAL; -- } --} -- --static int __init x1205_init(void) --{ -- return i2c_add_driver(&x1205_driver); --} -- --static void __exit x1205_exit(void) --{ -- i2c_del_driver(&x1205_driver); --} -- --MODULE_AUTHOR( -- "Karen Spearel <kas11@tampabay.rr.com>, " -- "Alessandro Zummo <a.zummo@towertech.it>"); --MODULE_DESCRIPTION("Xicor X1205 RTC driver"); --MODULE_LICENSE("GPL"); --MODULE_VERSION(DRV_VERSION); -- --EXPORT_SYMBOL_GPL(x1205_do_command); --EXPORT_SYMBOL_GPL(x1205_direct_attach); -- --module_init(x1205_init); --module_exit(x1205_exit); ---- linux-ixp4xx.orig/drivers/i2c/chips/Makefile 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/drivers/i2c/chips/Makefile 2006-03-08 01:59:26.000000000 +0100 -@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o - obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o - obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o - obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o --obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o - obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o - obj-$(CONFIG_TPS65010) += tps65010.o --obj-$(CONFIG_RTC_X1205_I2C) += x1205.o - - ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) - EXTRA_CFLAGS += -DDEBUG ---- linux-ixp4xx.orig/drivers/i2c/chips/rtc8564.c 2006-03-08 01:59:09.000000000 +0100 -+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 -@@ -1,385 +0,0 @@ --/* -- * linux/drivers/i2c/chips/rtc8564.c -- * -- * Copyright (C) 2002-2004 Stefan Eletzhofer -- * -- * based on linux/drivers/acron/char/pcf8583.c -- * Copyright (C) 2000 Russell King -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * Driver for system3's EPSON RTC 8564 chip -- */ --#include <linux/module.h> --#include <linux/kernel.h> --#include <linux/bcd.h> --#include <linux/i2c.h> --#include <linux/slab.h> --#include <linux/string.h> --#include <linux/rtc.h> /* get the user-level API */ --#include <linux/init.h> -- --#include "rtc8564.h" -- --#ifdef DEBUG --# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0); --#else --# define _DBG(x, fmt, args...) do { } while(0); --#endif -- --#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \ -- "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \ -- (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \ -- (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl); -- --struct rtc8564_data { -- struct i2c_client client; -- u16 ctrl; --}; -- --static inline u8 _rtc8564_ctrl1(struct i2c_client *client) --{ -- struct rtc8564_data *data = i2c_get_clientdata(client); -- return data->ctrl & 0xff; --} --static inline u8 _rtc8564_ctrl2(struct i2c_client *client) --{ -- struct rtc8564_data *data = i2c_get_clientdata(client); -- return (data->ctrl & 0xff00) >> 8; --} -- --#define CTRL1(c) _rtc8564_ctrl1(c) --#define CTRL2(c) _rtc8564_ctrl2(c) -- --static int debug;; --module_param(debug, int, S_IRUGO | S_IWUSR); -- --static struct i2c_driver rtc8564_driver; -- --static unsigned short ignore[] = { I2C_CLIENT_END }; --static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; -- --static struct i2c_client_address_data addr_data = { -- .normal_i2c = normal_addr, -- .probe = ignore, -- .ignore = ignore, --}; -- --static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem); --static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem); -- --static int rtc8564_read(struct i2c_client *client, unsigned char adr, -- unsigned char *buf, unsigned char len) --{ -- int ret = -EIO; -- unsigned char addr[1] = { adr }; -- struct i2c_msg msgs[2] = { -- {client->addr, 0, 1, addr}, -- {client->addr, I2C_M_RD, len, buf} -- }; -- -- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len); -- -- if (!buf) { -- ret = -EINVAL; -- goto done; -- } -- -- ret = i2c_transfer(client->adapter, msgs, 2); -- if (ret == 2) { -- ret = 0; -- } -- --done: -- return ret; --} -- --static int rtc8564_write(struct i2c_client *client, unsigned char adr, -- unsigned char *data, unsigned char len) --{ -- int ret = 0; -- unsigned char _data[16]; -- struct i2c_msg wr; -- int i; -- -- if (!data || len > 15) { -- ret = -EINVAL; -- goto done; -- } -- -- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len); -- -- _data[0] = adr; -- for (i = 0; i < len; i++) { -- _data[i + 1] = data[i]; -- _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]); -- } -- -- wr.addr = client->addr; -- wr.flags = 0; -- wr.len = len + 1; -- wr.buf = _data; -- -- ret = i2c_transfer(client->adapter, &wr, 1); -- if (ret == 1) { -- ret = 0; -- } -- --done: -- return ret; --} -- --static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) --{ -- int ret; -- struct i2c_client *new_client; -- struct rtc8564_data *d; -- unsigned char data[10]; -- unsigned char ad[1] = { 0 }; -- struct i2c_msg ctrl_wr[1] = { -- {addr, 0, 2, data} -- }; -- struct i2c_msg ctrl_rd[2] = { -- {addr, 0, 1, ad}, -- {addr, I2C_M_RD, 2, data} -- }; -- -- d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL); -- if (!d) { -- ret = -ENOMEM; -- goto done; -- } -- new_client = &d->client; -- -- strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); -- i2c_set_clientdata(new_client, d); -- new_client->addr = addr; -- new_client->adapter = adap; -- new_client->driver = &rtc8564_driver; -- -- _DBG(1, "client=%p", new_client); -- -- /* init ctrl1 reg */ -- data[0] = 0; -- data[1] = 0; -- ret = i2c_transfer(new_client->adapter, ctrl_wr, 1); -- if (ret != 1) { -- printk(KERN_INFO "rtc8564: cant init ctrl1\n"); -- ret = -ENODEV; -- goto done; -- } -- -- /* read back ctrl1 and ctrl2 */ -- ret = i2c_transfer(new_client->adapter, ctrl_rd, 2); -- if (ret != 2) { -- printk(KERN_INFO "rtc8564: cant read ctrl\n"); -- ret = -ENODEV; -- goto done; -- } -- -- d->ctrl = data[0] | (data[1] << 8); -- -- _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x", -- data[0], data[1]); -- -- ret = i2c_attach_client(new_client); --done: -- if (ret) { -- kfree(d); -- } -- return ret; --} -- --static int rtc8564_probe(struct i2c_adapter *adap) --{ -- return i2c_probe(adap, &addr_data, rtc8564_attach); --} -- --static int rtc8564_detach(struct i2c_client *client) --{ -- i2c_detach_client(client); -- kfree(i2c_get_clientdata(client)); -- return 0; --} -- --static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) --{ -- int ret = -EIO; -- unsigned char buf[15]; -- -- _DBG(1, "client=%p, dt=%p", client, dt); -- -- if (!dt) -- return -EINVAL; -- -- memset(buf, 0, sizeof(buf)); -- -- ret = rtc8564_read(client, 0, buf, 15); -- if (ret) -- return ret; -- -- /* century stored in minute alarm reg */ -- dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]); -- dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); -- dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f); -- dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7); -- dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); -- -- dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f); -- dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; -- dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f); -- dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f); -- -- _DBGRTCTM(2, *dt); -- -- return 0; --} -- --static int --rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) --{ -- int ret, len = 5; -- unsigned char buf[15]; -- -- _DBG(1, "client=%p, dt=%p", client, dt); -- -- if (!dt) -- return -EINVAL; -- -- _DBGRTCTM(2, *dt); -- -- buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; -- buf[RTC8564_REG_CTRL2] = CTRL2(client); -- buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs); -- buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins); -- buf[RTC8564_REG_HR] = BIN2BCD(dt->hours); -- -- if (datetoo) { -- len += 5; -- buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday); -- buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday); -- buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f; -- /* century stored in minute alarm reg */ -- buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100); -- buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100); -- } -- -- ret = rtc8564_write(client, 0, buf, len); -- if (ret) { -- _DBG(1, "error writing data! %d", ret); -- } -- -- buf[RTC8564_REG_CTRL1] = CTRL1(client); -- ret = rtc8564_write(client, 0, buf, 1); -- if (ret) { -- _DBG(1, "error writing data! %d", ret); -- } -- -- return ret; --} -- --static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl) --{ -- struct rtc8564_data *data = i2c_get_clientdata(client); -- -- if (!ctrl) -- return -1; -- -- *ctrl = data->ctrl; -- return 0; --} -- --static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl) --{ -- struct rtc8564_data *data = i2c_get_clientdata(client); -- unsigned char buf[2]; -- -- if (!ctrl) -- return -1; -- -- buf[0] = *ctrl & 0xff; -- buf[1] = (*ctrl & 0xff00) >> 8; -- data->ctrl = *ctrl; -- -- return rtc8564_write(client, 0, buf, 2); --} -- --static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem) --{ -- -- if (!mem) -- return -EINVAL; -- -- return rtc8564_read(client, mem->loc, mem->data, mem->nr); --} -- --static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem) --{ -- -- if (!mem) -- return -EINVAL; -- -- return rtc8564_write(client, mem->loc, mem->data, mem->nr); --} -- --static int --rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) --{ -- -- _DBG(1, "cmd=%d", cmd); -- -- switch (cmd) { -- case RTC_GETDATETIME: -- return rtc8564_get_datetime(client, arg); -- -- case RTC_SETTIME: -- return rtc8564_set_datetime(client, arg, 0); -- -- case RTC_SETDATETIME: -- return rtc8564_set_datetime(client, arg, 1); -- -- case RTC_GETCTRL: -- return rtc8564_get_ctrl(client, arg); -- -- case RTC_SETCTRL: -- return rtc8564_set_ctrl(client, arg); -- -- case MEM_READ: -- return rtc8564_read_mem(client, arg); -- -- case MEM_WRITE: -- return rtc8564_write_mem(client, arg); -- -- default: -- return -EINVAL; -- } --} -- --static struct i2c_driver rtc8564_driver = { -- .driver = { -- .name = "RTC8564", -- }, -- .id = I2C_DRIVERID_RTC8564, -- .attach_adapter = rtc8564_probe, -- .detach_client = rtc8564_detach, -- .command = rtc8564_command --}; -- --static __init int rtc8564_init(void) --{ -- return i2c_add_driver(&rtc8564_driver); --} -- --static __exit void rtc8564_exit(void) --{ -- i2c_del_driver(&rtc8564_driver); --} -- --MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>"); --MODULE_DESCRIPTION("EPSON RTC8564 Driver"); --MODULE_LICENSE("GPL"); -- --module_init(rtc8564_init); --module_exit(rtc8564_exit); ---- linux-ixp4xx.orig/drivers/i2c/chips/rtc8564.h 2006-03-08 01:59:09.000000000 +0100 -+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 -@@ -1,78 +0,0 @@ --/* -- * linux/drivers/i2c/chips/rtc8564.h -- * -- * Copyright (C) 2002-2004 Stefan Eletzhofer -- * -- * based on linux/drivers/acron/char/pcf8583.h -- * Copyright (C) 2000 Russell King -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ --struct rtc_tm { -- unsigned char secs; -- unsigned char mins; -- unsigned char hours; -- unsigned char mday; -- unsigned char mon; -- unsigned short year; /* xxxx 4 digits :) */ -- unsigned char wday; -- unsigned char vl; --}; -- --struct mem { -- unsigned int loc; -- unsigned int nr; -- unsigned char *data; --}; -- --#define RTC_GETDATETIME 0 --#define RTC_SETTIME 1 --#define RTC_SETDATETIME 2 --#define RTC_GETCTRL 3 --#define RTC_SETCTRL 4 --#define MEM_READ 5 --#define MEM_WRITE 6 -- --#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */ --#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */ --#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */ --#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */ --#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */ --#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */ --#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */ --#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */ --#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */ --#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */ --#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */ --#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */ --#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */ --#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */ --#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */ --#define RTC8564_REG_TIMER 0xf /* 8 bit binary */ -- --/* Control reg */ --#define RTC8564_CTRL1_TEST1 (1<<3) --#define RTC8564_CTRL1_STOP (1<<5) --#define RTC8564_CTRL1_TEST2 (1<<7) -- --#define RTC8564_CTRL2_TIE (1<<0) --#define RTC8564_CTRL2_AIE (1<<1) --#define RTC8564_CTRL2_TF (1<<2) --#define RTC8564_CTRL2_AF (1<<3) --#define RTC8564_CTRL2_TI_TP (1<<4) -- --/* CLKOUT frequencies */ --#define RTC8564_FD_32768HZ (0x0) --#define RTC8564_FD_1024HZ (0x1) --#define RTC8564_FD_32 (0x2) --#define RTC8564_FD_1HZ (0x3) -- --/* Timer CTRL */ --#define RTC8564_TD_4096HZ (0x0) --#define RTC8564_TD_64HZ (0x1) --#define RTC8564_TD_1HZ (0x2) --#define RTC8564_TD_1_60HZ (0x3) -- --#define I2C_DRIVERID_RTC8564 0xf000 ---- linux-ixp4xx.orig/include/linux/x1205.h 2006-03-08 01:59:09.000000000 +0100 -+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 -@@ -1,31 +0,0 @@ --/* -- * x1205.h - defines for drivers/i2c/chips/x1205.c -- * Copyright 2004 Karen Spearel -- * Copyright 2005 Alessandro Zummo -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- */ -- --#ifndef __LINUX_X1205_H__ --#define __LINUX_X1205_H__ -- --/* commands */ -- --#define X1205_CMD_GETDATETIME 0 --#define X1205_CMD_SETTIME 1 --#define X1205_CMD_SETDATETIME 2 --#define X1205_CMD_GETALARM 3 --#define X1205_CMD_SETALARM 4 --#define X1205_CMD_GETDTRIM 5 --#define X1205_CMD_SETDTRIM 6 --#define X1205_CMD_GETATRIM 7 --#define X1205_CMD_SETATRIM 8 -- --extern int x1205_do_command(unsigned int cmd, void *arg); --extern int x1205_direct_attach(int adapter_id, -- struct i2c_client_address_data *address_data); -- --#endif /* __LINUX_X1205_H__ */ ---- linux-ixp4xx.orig/drivers/i2c/chips/Kconfig 2006-03-08 01:59:09.000000000 +0100 -1+++ linux-ixp4xx/drivers/i2c/chips/Kconfig 2006-03-08 01:59:26.000000000 +0100 -@@ -74,15 +74,6 @@ config SENSORS_RTC8564 - This driver can also be built as a module. If so, the module - will be called pcf8591. - --config SENSORS_RTC8564 -- tristate "Epson 8564 RTC chip" -- depends on I2C && EXPERIMENTAL -- help -- If you say yes here you get support for the Epson 8564 RTC chip. -- -- This driver can also be built as a module. If so, the module -- will be called i2c-rtc8564. -- - config ISP1301_OMAP - tristate "Philips ISP1301 with OMAP OTG" - depends on I2C && ARCH_OMAP_OTG -@@ -144,13 +135,4 @@ config RTC_X1205_I2C - This driver can also be built as a module. If so, the module - will be called max6875. - --config RTC_X1205_I2C -- tristate "Xicor X1205 RTC chip" -- depends on I2C && EXPERIMENTAL -- help -- If you say yes here you get support for the Xicor X1205 RTC chip. -- -- This driver can also be built as a module. If so, the module -- will be called x1205. -- - endmenu ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-sysfs.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,124 @@ -+/* -+ * RTC subsystem, sysfs interface -+ * -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+ -+/* device attributes */ -+ -+static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf) -+{ -+ return sprintf(buf, "%s\n", to_rtc_device(dev)->name); -+} -+static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL); -+ -+static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) -+{ -+ ssize_t retval; -+ struct rtc_time tm; -+ -+ retval = rtc_read_time(dev, &tm); -+ if (retval == 0) { -+ retval = sprintf(buf, "%04d-%02d-%02d\n", -+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); -+ } -+ -+ return retval; -+} -+static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL); -+ -+static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) -+{ -+ ssize_t retval; -+ struct rtc_time tm; -+ -+ retval = rtc_read_time(dev, &tm); -+ if (retval == 0) { -+ retval = sprintf(buf, "%02d:%02d:%02d\n", -+ tm.tm_hour, tm.tm_min, tm.tm_sec); -+ } -+ -+ return retval; -+} -+static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL); -+ -+static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) -+{ -+ ssize_t retval; -+ struct rtc_time tm; -+ -+ retval = rtc_read_time(dev, &tm); -+ if (retval == 0) { -+ unsigned long time; -+ rtc_tm_to_time(&tm, &time); -+ retval = sprintf(buf, "%lu\n", time); -+ } -+ -+ return retval; -+} -+static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL); -+ -+static struct attribute *rtc_attrs[] = { -+ &class_device_attr_name.attr, -+ &class_device_attr_date.attr, -+ &class_device_attr_time.attr, -+ &class_device_attr_since_epoch.attr, -+ NULL, -+}; -+ -+static struct attribute_group rtc_attr_group = { -+ .attrs = rtc_attrs, -+}; -+ -+static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ int err; -+ -+ dev_info(class_dev->dev, "rtc intf: sysfs\n"); -+ -+ err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group); -+ if (err) -+ dev_err(class_dev->dev, -+ "failed to create sysfs attributes\n"); -+ -+ return err; -+} -+ -+static void rtc_sysfs_remove_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ sysfs_remove_group(&class_dev->kobj, &rtc_attr_group); -+} -+ -+/* interface registration */ -+ -+static struct class_interface rtc_sysfs_interface = { -+ .add = &rtc_sysfs_add_device, -+ .remove = &rtc_sysfs_remove_device, -+}; -+ -+static int __init rtc_sysfs_init(void) -+{ -+ return rtc_interface_register(&rtc_sysfs_interface); -+} -+ -+static void __exit rtc_sysfs_exit(void) -+{ -+ class_interface_unregister(&rtc_sysfs_interface); -+} -+ -+module_init(rtc_sysfs_init); -+module_exit(rtc_sysfs_exit); -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("RTC class sysfs interface"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-proc.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,162 @@ -+/* -+ * RTC subsystem, proc interface -+ * -+ * Copyright (C) 2005-06 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on arch/arm/common/rtctime.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+#include <linux/proc_fs.h> -+#include <linux/seq_file.h> -+ -+static struct class_device *rtc_dev = NULL; -+static DEFINE_MUTEX(rtc_lock); -+ -+static int rtc_proc_show(struct seq_file *seq, void *offset) -+{ -+ int err; -+ struct class_device *class_dev = seq->private; -+ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops; -+ struct rtc_wkalrm alrm; -+ struct rtc_time tm; -+ -+ err = rtc_read_time(class_dev, &tm); -+ if (err == 0) { -+ seq_printf(seq, -+ "rtc_time\t: %02d:%02d:%02d\n" -+ "rtc_date\t: %04d-%02d-%02d\n", -+ tm.tm_hour, tm.tm_min, tm.tm_sec, -+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); -+ } -+ -+ err = rtc_read_alarm(class_dev, &alrm); -+ if (err == 0) { -+ seq_printf(seq, "alrm_time\t: "); -+ if ((unsigned int)alrm.time.tm_hour <= 24) -+ seq_printf(seq, "%02d:", alrm.time.tm_hour); -+ else -+ seq_printf(seq, "**:"); -+ if ((unsigned int)alrm.time.tm_min <= 59) -+ seq_printf(seq, "%02d:", alrm.time.tm_min); -+ else -+ seq_printf(seq, "**:"); -+ if ((unsigned int)alrm.time.tm_sec <= 59) -+ seq_printf(seq, "%02d\n", alrm.time.tm_sec); -+ else -+ seq_printf(seq, "**\n"); -+ -+ seq_printf(seq, "alrm_date\t: "); -+ if ((unsigned int)alrm.time.tm_year <= 200) -+ seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); -+ else -+ seq_printf(seq, "****-"); -+ if ((unsigned int)alrm.time.tm_mon <= 11) -+ seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); -+ else -+ seq_printf(seq, "**-"); -+ if ((unsigned int)alrm.time.tm_mday <= 31) -+ seq_printf(seq, "%02d\n", alrm.time.tm_mday); -+ else -+ seq_printf(seq, "**\n"); -+ seq_printf(seq, "alrm_wakeup\t: %s\n", -+ alrm.enabled ? "yes" : "no"); -+ seq_printf(seq, "alrm_pending\t: %s\n", -+ alrm.pending ? "yes" : "no"); -+ } -+ -+ if (ops->proc) -+ ops->proc(class_dev->dev, seq); -+ -+ return 0; -+} -+ -+static int rtc_proc_open(struct inode *inode, struct file *file) -+{ -+ struct class_device *class_dev = PDE(inode)->data; -+ -+ if (!try_module_get(THIS_MODULE)) -+ return -ENODEV; -+ -+ return single_open(file, rtc_proc_show, class_dev); -+} -+ -+static int rtc_proc_release(struct inode *inode, struct file *file) -+{ -+ int res = single_release(inode, file); -+ module_put(THIS_MODULE); -+ return res; -+} -+ -+static struct file_operations rtc_proc_fops = { -+ .open = rtc_proc_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = rtc_proc_release, -+}; -+ -+static int rtc_proc_add_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ mutex_lock(&rtc_lock); -+ if (rtc_dev == NULL) { -+ struct proc_dir_entry *ent; -+ -+ rtc_dev = class_dev; -+ -+ ent = create_proc_entry("driver/rtc", 0, NULL); -+ if (ent) { -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ ent->proc_fops = &rtc_proc_fops; -+ ent->owner = rtc->owner; -+ ent->data = class_dev; -+ -+ dev_info(class_dev->dev, "rtc intf: proc\n"); -+ } -+ else -+ rtc_dev = NULL; -+ } -+ mutex_unlock(&rtc_lock); -+ -+ return 0; -+} -+ -+static void rtc_proc_remove_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ mutex_lock(&rtc_lock); -+ if (rtc_dev == class_dev) { -+ remove_proc_entry("driver/rtc", NULL); -+ rtc_dev = NULL; -+ } -+ mutex_unlock(&rtc_lock); -+} -+ -+static struct class_interface rtc_proc_interface = { -+ .add = &rtc_proc_add_device, -+ .remove = &rtc_proc_remove_device, -+}; -+ -+static int __init rtc_proc_init(void) -+{ -+ return rtc_interface_register(&rtc_proc_interface); -+} -+ -+static void __exit rtc_proc_exit(void) -+{ -+ class_interface_unregister(&rtc_proc_interface); -+} -+ -+module_init(rtc_proc_init); -+module_exit(rtc_proc_exit); -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("RTC class proc interface"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-dev.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,382 @@ -+/* -+ * RTC subsystem, dev interface -+ * -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on arch/arm/common/rtctime.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; version 2 of the License. -+*/ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+ -+static struct class *rtc_dev_class; -+static dev_t rtc_devt; -+ -+#define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ -+ -+static int rtc_dev_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct rtc_device *rtc = container_of(inode->i_cdev, -+ struct rtc_device, char_dev); -+ struct rtc_class_ops *ops = rtc->ops; -+ -+ /* We keep the lock as long as the device is in use -+ * and return immediately if busy -+ */ -+ if (!(mutex_trylock(&rtc->char_lock))) -+ return -EBUSY; -+ -+ file->private_data = &rtc->class_dev; -+ -+ err = ops->open ? ops->open(rtc->class_dev.dev) : 0; -+ if (err == 0) { -+ spin_lock_irq(&rtc->irq_lock); -+ rtc->irq_data = 0; -+ spin_unlock_irq(&rtc->irq_lock); -+ -+ return 0; -+ } -+ -+ /* something has gone wrong, release the lock */ -+ mutex_unlock(&rtc->char_lock); -+ return err; -+} -+ -+ -+static ssize_t -+rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) -+{ -+ struct rtc_device *rtc = to_rtc_device(file->private_data); -+ -+ DECLARE_WAITQUEUE(wait, current); -+ unsigned long data; -+ ssize_t ret; -+ -+ if (count < sizeof(unsigned long)) -+ return -EINVAL; -+ -+ add_wait_queue(&rtc->irq_queue, &wait); -+ do { -+ __set_current_state(TASK_INTERRUPTIBLE); -+ -+ spin_lock_irq(&rtc->irq_lock); -+ data = rtc->irq_data; -+ rtc->irq_data = 0; -+ spin_unlock_irq(&rtc->irq_lock); -+ -+ if (data != 0) { -+ ret = 0; -+ break; -+ } -+ if (file->f_flags & O_NONBLOCK) { -+ ret = -EAGAIN; -+ break; -+ } -+ if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ break; -+ } -+ schedule(); -+ } while (1); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&rtc->irq_queue, &wait); -+ -+ if (ret == 0) { -+ /* Check for any data updates */ -+ if (rtc->ops->read_callback) -+ data = rtc->ops->read_callback(rtc->class_dev.dev, data); -+ -+ ret = put_user(data, (unsigned long __user *)buf); -+ if (ret == 0) -+ ret = sizeof(unsigned long); -+ } -+ return ret; -+} -+ -+static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) -+{ -+ struct rtc_device *rtc = to_rtc_device(file->private_data); -+ unsigned long data; -+ -+ poll_wait(file, &rtc->irq_queue, wait); -+ -+ data = rtc->irq_data; -+ -+ return (data != 0) ? (POLLIN | POLLRDNORM) : 0; -+} -+ -+static int rtc_dev_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ int err = 0; -+ struct class_device *class_dev = file->private_data; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ struct rtc_class_ops *ops = rtc->ops; -+ struct rtc_time tm; -+ struct rtc_wkalrm alarm; -+ void __user *uarg = (void __user *) arg; -+ -+ /* avoid conflicting IRQ users */ -+ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { -+ spin_lock(&rtc->irq_task_lock); -+ if (rtc->irq_task) -+ err = -EBUSY; -+ spin_unlock(&rtc->irq_task_lock); -+ -+ if (err < 0) -+ return err; -+ } -+ -+ /* try the driver's ioctl interface */ -+ if (ops->ioctl) { -+ err = ops->ioctl(class_dev->dev, cmd, arg); -+ if (err != -EINVAL) -+ return err; -+ } -+ -+ /* if the driver does not provide the ioctl interface -+ * or if that particular ioctl was not implemented -+ * (-EINVAL), we will try to emulate here. -+ */ -+ -+ switch (cmd) { -+ case RTC_ALM_READ: -+ err = rtc_read_alarm(class_dev, &alarm); -+ if (err < 0) -+ return err; -+ -+ if (copy_to_user(uarg, &alarm.time, sizeof(tm))) -+ return -EFAULT; -+ break; -+ -+ case RTC_ALM_SET: -+ if (copy_from_user(&alarm.time, uarg, sizeof(tm))) -+ return -EFAULT; -+ -+ alarm.enabled = 0; -+ alarm.pending = 0; -+ alarm.time.tm_mday = -1; -+ alarm.time.tm_mon = -1; -+ alarm.time.tm_year = -1; -+ alarm.time.tm_wday = -1; -+ alarm.time.tm_yday = -1; -+ alarm.time.tm_isdst = -1; -+ err = rtc_set_alarm(class_dev, &alarm); -+ break; -+ -+ case RTC_RD_TIME: -+ err = rtc_read_time(class_dev, &tm); -+ if (err < 0) -+ return err; -+ -+ if (copy_to_user(uarg, &tm, sizeof(tm))) -+ return -EFAULT; -+ break; -+ -+ case RTC_SET_TIME: -+ if (!capable(CAP_SYS_TIME)) -+ return -EACCES; -+ -+ if (copy_from_user(&tm, uarg, sizeof(tm))) -+ return -EFAULT; -+ -+ err = rtc_set_time(class_dev, &tm); -+ break; -+#if 0 -+ case RTC_EPOCH_SET: -+#ifndef rtc_epoch -+ /* -+ * There were no RTC clocks before 1900. -+ */ -+ if (arg < 1900) { -+ err = -EINVAL; -+ break; -+ } -+ if (!capable(CAP_SYS_TIME)) { -+ err = -EACCES; -+ break; -+ } -+ rtc_epoch = arg; -+ err = 0; -+#endif -+ break; -+ -+ case RTC_EPOCH_READ: -+ err = put_user(rtc_epoch, (unsigned long __user *)uarg); -+ break; -+#endif -+ case RTC_WKALM_SET: -+ if (copy_from_user(&alarm, uarg, sizeof(alarm))) -+ return -EFAULT; -+ -+ err = rtc_set_alarm(class_dev, &alarm); -+ break; -+ -+ case RTC_WKALM_RD: -+ err = rtc_read_alarm(class_dev, &alarm); -+ if (err < 0) -+ return err; -+ -+ if (copy_to_user(uarg, &alarm, sizeof(alarm))) -+ return -EFAULT; -+ break; -+ -+ default: -+ err = -EINVAL; -+ break; -+ } -+ -+ return err; -+} -+ -+static int rtc_dev_release(struct inode *inode, struct file *file) -+{ -+ struct rtc_device *rtc = to_rtc_device(file->private_data); -+ -+ if (rtc->ops->release) -+ rtc->ops->release(rtc->class_dev.dev); -+ -+ mutex_unlock(&rtc->char_lock); -+ return 0; -+} -+ -+static int rtc_dev_fasync(int fd, struct file *file, int on) -+{ -+ struct rtc_device *rtc = to_rtc_device(file->private_data); -+ return fasync_helper(fd, file, on, &rtc->async_queue); -+} -+ -+static struct file_operations rtc_dev_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = rtc_dev_read, -+ .poll = rtc_dev_poll, -+ .ioctl = rtc_dev_ioctl, -+ .open = rtc_dev_open, -+ .release = rtc_dev_release, -+ .fasync = rtc_dev_fasync, -+}; -+ -+/* insertion/removal hooks */ -+ -+static int rtc_dev_add_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ int err = 0; -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ if (rtc->id >= RTC_DEV_MAX) { -+ dev_err(class_dev->dev, "too many RTCs\n"); -+ return -EINVAL; -+ } -+ -+ mutex_init(&rtc->char_lock); -+ spin_lock_init(&rtc->irq_lock); -+ init_waitqueue_head(&rtc->irq_queue); -+ -+ cdev_init(&rtc->char_dev, &rtc_dev_fops); -+ rtc->char_dev.owner = rtc->owner; -+ -+ if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) { -+ cdev_del(&rtc->char_dev); -+ dev_err(class_dev->dev, -+ "failed to add char device %d:%d\n", -+ MAJOR(rtc_devt), rtc->id); -+ return -ENODEV; -+ } -+ -+ rtc->rtc_dev = class_device_create(rtc_dev_class, NULL, -+ MKDEV(MAJOR(rtc_devt), rtc->id), -+ class_dev->dev, "rtc%d", rtc->id); -+ if (IS_ERR(rtc->rtc_dev)) { -+ dev_err(class_dev->dev, "cannot create rtc_dev device\n"); -+ err = PTR_ERR(rtc->rtc_dev); -+ goto err_cdev_del; -+ } -+ -+ dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n", -+ MAJOR(rtc->rtc_dev->devt), -+ MINOR(rtc->rtc_dev->devt)); -+ -+ return 0; -+ -+err_cdev_del: -+ -+ cdev_del(&rtc->char_dev); -+ return err; -+} -+ -+static void rtc_dev_remove_device(struct class_device *class_dev, -+ struct class_interface *class_intf) -+{ -+ struct rtc_device *rtc = to_rtc_device(class_dev); -+ -+ if (rtc->rtc_dev) { -+ dev_dbg(class_dev->dev, "removing char %d:%d\n", -+ MAJOR(rtc->rtc_dev->devt), -+ MINOR(rtc->rtc_dev->devt)); -+ -+ class_device_unregister(rtc->rtc_dev); -+ cdev_del(&rtc->char_dev); -+ } -+} -+ -+/* interface registration */ -+ -+static struct class_interface rtc_dev_interface = { -+ .add = &rtc_dev_add_device, -+ .remove = &rtc_dev_remove_device, -+}; -+ -+static int __init rtc_dev_init(void) -+{ -+ int err; -+ -+ rtc_dev_class = class_create(THIS_MODULE, "rtc-dev"); -+ if (IS_ERR(rtc_dev_class)) -+ return PTR_ERR(rtc_dev_class); -+ -+ err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); -+ if (err < 0) { -+ printk(KERN_ERR "%s: failed to allocate char dev region\n", -+ __FILE__); -+ goto err_destroy_class; -+ } -+ -+ err = rtc_interface_register(&rtc_dev_interface); -+ if (err < 0) { -+ printk(KERN_ERR "%s: failed to register the interface\n", -+ __FILE__); -+ goto err_unregister_chrdev; -+ } -+ -+ return 0; -+ -+err_unregister_chrdev: -+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); -+ -+err_destroy_class: -+ class_destroy(rtc_dev_class); -+ -+ return err; -+} -+ -+static void __exit rtc_dev_exit(void) -+{ -+ class_interface_unregister(&rtc_dev_interface); -+ class_destroy(rtc_dev_class); -+ unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); -+} -+ -+module_init(rtc_dev_init); -+module_exit(rtc_dev_exit); -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("RTC class dev interface"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-x1205.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,619 @@ -+/* -+ * An i2c driver for the Xicor/Intersil X1205 RTC -+ * Copyright 2004 Karen Spearel -+ * Copyright 2005 Alessandro Zummo -+ * -+ * please send all reports to: -+ * Karen Spearel <kas111 at gmail dot com> -+ * Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on a lot of other RTC drivers. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/i2c.h> -+#include <linux/bcd.h> -+#include <linux/rtc.h> -+#include <linux/delay.h> -+ -+#define DRV_VERSION "1.0.6" -+ -+/* Addresses to scan: none. This chip is located at -+ * 0x6f and uses a two bytes register addressing. -+ * Two bytes need to be written to read a single register, -+ * while most other chips just require one and take the second -+ * one as the data to be written. To prevent corrupting -+ * unknown chips, the user must explicitely set the probe parameter. -+ */ -+ -+static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD; -+ -+/* offsets into CCR area */ -+ -+#define CCR_SEC 0 -+#define CCR_MIN 1 -+#define CCR_HOUR 2 -+#define CCR_MDAY 3 -+#define CCR_MONTH 4 -+#define CCR_YEAR 5 -+#define CCR_WDAY 6 -+#define CCR_Y2K 7 -+ -+#define X1205_REG_SR 0x3F /* status register */ -+#define X1205_REG_Y2K 0x37 -+#define X1205_REG_DW 0x36 -+#define X1205_REG_YR 0x35 -+#define X1205_REG_MO 0x34 -+#define X1205_REG_DT 0x33 -+#define X1205_REG_HR 0x32 -+#define X1205_REG_MN 0x31 -+#define X1205_REG_SC 0x30 -+#define X1205_REG_DTR 0x13 -+#define X1205_REG_ATR 0x12 -+#define X1205_REG_INT 0x11 -+#define X1205_REG_0 0x10 -+#define X1205_REG_Y2K1 0x0F -+#define X1205_REG_DWA1 0x0E -+#define X1205_REG_YRA1 0x0D -+#define X1205_REG_MOA1 0x0C -+#define X1205_REG_DTA1 0x0B -+#define X1205_REG_HRA1 0x0A -+#define X1205_REG_MNA1 0x09 -+#define X1205_REG_SCA1 0x08 -+#define X1205_REG_Y2K0 0x07 -+#define X1205_REG_DWA0 0x06 -+#define X1205_REG_YRA0 0x05 -+#define X1205_REG_MOA0 0x04 -+#define X1205_REG_DTA0 0x03 -+#define X1205_REG_HRA0 0x02 -+#define X1205_REG_MNA0 0x01 -+#define X1205_REG_SCA0 0x00 -+ -+#define X1205_CCR_BASE 0x30 /* Base address of CCR */ -+#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ -+ -+#define X1205_SR_RTCF 0x01 /* Clock failure */ -+#define X1205_SR_WEL 0x02 /* Write Enable Latch */ -+#define X1205_SR_RWEL 0x04 /* Register Write Enable */ -+ -+#define X1205_DTR_DTR0 0x01 -+#define X1205_DTR_DTR1 0x02 -+#define X1205_DTR_DTR2 0x04 -+ -+#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ -+ -+/* Prototypes */ -+static int x1205_attach(struct i2c_adapter *adapter); -+static int x1205_detach(struct i2c_client *client); -+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); -+ -+static struct i2c_driver x1205_driver = { -+ .driver = { -+ .name = "x1205", -+ }, -+ .attach_adapter = &x1205_attach, -+ .detach_client = &x1205_detach, -+}; -+ -+/* -+ * In the routines that deal directly with the x1205 hardware, we use -+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch -+ * Epoch is initialized as 2000. Time is set to UTC. -+ */ -+static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, -+ unsigned char reg_base) -+{ -+ unsigned char dt_addr[2] = { 0, reg_base }; -+ -+ unsigned char buf[8]; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, dt_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 8, buf }, /* read date */ -+ }; -+ -+ /* read date registers */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ dev_dbg(&client->dev, -+ "%s: raw read data - sec=%02x, min=%02x, hr=%02x, " -+ "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", -+ __FUNCTION__, -+ buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); -+ -+ tm->tm_sec = BCD2BIN(buf[CCR_SEC]); -+ tm->tm_min = BCD2BIN(buf[CCR_MIN]); -+ tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ -+ tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); -+ tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */ -+ tm->tm_year = BCD2BIN(buf[CCR_YEAR]) -+ + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900; -+ tm->tm_wday = buf[CCR_WDAY]; -+ -+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ return 0; -+} -+ -+static int x1205_get_status(struct i2c_client *client, unsigned char *sr) -+{ -+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 1, sr }, /* read status */ -+ }; -+ -+ /* read status register */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, -+ int datetoo, u8 reg_base) -+{ -+ int i, xfer; -+ unsigned char buf[8]; -+ -+ static const unsigned char wel[3] = { 0, X1205_REG_SR, -+ X1205_SR_WEL }; -+ -+ static const unsigned char rwel[3] = { 0, X1205_REG_SR, -+ X1205_SR_WEL | X1205_SR_RWEL }; -+ -+ static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; -+ -+ dev_dbg(&client->dev, -+ "%s: secs=%d, mins=%d, hours=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour); -+ -+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec); -+ buf[CCR_MIN] = BIN2BCD(tm->tm_min); -+ -+ /* set hour and 24hr bit */ -+ buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; -+ -+ /* should we also set the date? */ -+ if (datetoo) { -+ dev_dbg(&client->dev, -+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); -+ -+ /* month, 1 - 12 */ -+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1); -+ -+ /* year, since the rtc epoch*/ -+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); -+ buf[CCR_WDAY] = tm->tm_wday & 0x07; -+ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); -+ } -+ -+ /* this sequence is required to unlock the chip */ -+ if ((xfer = i2c_master_send(client, wel, 3)) != 3) { -+ dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); -+ return -EIO; -+ } -+ -+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { -+ dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); -+ return -EIO; -+ } -+ -+ /* write register's data */ -+ for (i = 0; i < (datetoo ? 8 : 3); i++) { -+ unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; -+ -+ xfer = i2c_master_send(client, rdata, 3); -+ if (xfer != 3) { -+ dev_err(&client->dev, -+ "%s: xfer=%d addr=%02x, data=%02x\n", -+ __FUNCTION__, -+ xfer, rdata[1], rdata[2]); -+ return -EIO; -+ } -+ }; -+ -+ /* disable further writes */ -+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { -+ dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int x1205_fix_osc(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_time tm; -+ -+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0; -+ -+ if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0) -+ dev_err(&client->dev, -+ "unable to restart the oscillator\n"); -+ -+ return err; -+} -+ -+static int x1205_get_dtrim(struct i2c_client *client, int *trim) -+{ -+ unsigned char dtr; -+ static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ -+ }; -+ -+ /* read dtr register */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr); -+ -+ *trim = 0; -+ -+ if (dtr & X1205_DTR_DTR0) -+ *trim += 20; -+ -+ if (dtr & X1205_DTR_DTR1) -+ *trim += 10; -+ -+ if (dtr & X1205_DTR_DTR2) -+ *trim = -*trim; -+ -+ return 0; -+} -+ -+static int x1205_get_atrim(struct i2c_client *client, int *trim) -+{ -+ s8 atr; -+ static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, atr_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ -+ }; -+ -+ /* read atr register */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr); -+ -+ /* atr is a two's complement value on 6 bits, -+ * perform sign extension. The formula is -+ * Catr = (atr * 0.25pF) + 11.00pF. -+ */ -+ if (atr & 0x20) -+ atr |= 0xC0; -+ -+ dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr); -+ -+ *trim = (atr * 250) + 11000; -+ -+ dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim); -+ -+ return 0; -+} -+ -+struct x1205_limit -+{ -+ unsigned char reg, mask, min, max; -+}; -+ -+static int x1205_validate_client(struct i2c_client *client) -+{ -+ int i, xfer; -+ -+ /* Probe array. We will read the register at the specified -+ * address and check if the given bits are zero. -+ */ -+ static const unsigned char probe_zero_pattern[] = { -+ /* register, mask */ -+ X1205_REG_SR, 0x18, -+ X1205_REG_DTR, 0xF8, -+ X1205_REG_ATR, 0xC0, -+ X1205_REG_INT, 0x18, -+ X1205_REG_0, 0xFF, -+ }; -+ -+ static const struct x1205_limit probe_limits_pattern[] = { -+ /* register, mask, min, max */ -+ { X1205_REG_Y2K, 0xFF, 19, 20 }, -+ { X1205_REG_DW, 0xFF, 0, 6 }, -+ { X1205_REG_YR, 0xFF, 0, 99 }, -+ { X1205_REG_MO, 0xFF, 0, 12 }, -+ { X1205_REG_DT, 0xFF, 0, 31 }, -+ { X1205_REG_HR, 0x7F, 0, 23 }, -+ { X1205_REG_MN, 0xFF, 0, 59 }, -+ { X1205_REG_SC, 0xFF, 0, 59 }, -+ { X1205_REG_Y2K1, 0xFF, 19, 20 }, -+ { X1205_REG_Y2K0, 0xFF, 19, 20 }, -+ }; -+ -+ /* check that registers have bits a 0 where expected */ -+ for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) { -+ unsigned char buf; -+ -+ unsigned char addr[2] = { 0, probe_zero_pattern[i] }; -+ -+ struct i2c_msg msgs[2] = { -+ { client->addr, 0, 2, addr }, -+ { client->addr, I2C_M_RD, 1, &buf }, -+ }; -+ -+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { -+ dev_err(&client->adapter->dev, -+ "%s: could not read register %x\n", -+ __FUNCTION__, probe_zero_pattern[i]); -+ -+ return -EIO; -+ } -+ -+ if ((buf & probe_zero_pattern[i+1]) != 0) { -+ dev_err(&client->adapter->dev, -+ "%s: register=%02x, zero pattern=%d, value=%x\n", -+ __FUNCTION__, probe_zero_pattern[i], i, buf); -+ -+ return -ENODEV; -+ } -+ } -+ -+ /* check limits (only registers with bcd values) */ -+ for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) { -+ unsigned char reg, value; -+ -+ unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; -+ -+ struct i2c_msg msgs[2] = { -+ { client->addr, 0, 2, addr }, -+ { client->addr, I2C_M_RD, 1, ® }, -+ }; -+ -+ if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { -+ dev_err(&client->adapter->dev, -+ "%s: could not read register %x\n", -+ __FUNCTION__, probe_limits_pattern[i].reg); -+ -+ return -EIO; -+ } -+ -+ value = BCD2BIN(reg & probe_limits_pattern[i].mask); -+ -+ if (value > probe_limits_pattern[i].max || -+ value < probe_limits_pattern[i].min) { -+ dev_dbg(&client->adapter->dev, -+ "%s: register=%x, lim pattern=%d, value=%d\n", -+ __FUNCTION__, probe_limits_pattern[i].reg, -+ i, value); -+ -+ return -ENODEV; -+ } -+ } -+ -+ return 0; -+} -+ -+static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+ return x1205_get_datetime(to_i2c_client(dev), -+ &alrm->time, X1205_ALM0_BASE); -+} -+ -+static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+ return x1205_set_datetime(to_i2c_client(dev), -+ &alrm->time, 1, X1205_ALM0_BASE); -+} -+ -+static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ return x1205_get_datetime(to_i2c_client(dev), -+ tm, X1205_CCR_BASE); -+} -+ -+static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ return x1205_set_datetime(to_i2c_client(dev), -+ tm, 1, X1205_CCR_BASE); -+} -+ -+static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ int err, dtrim, atrim; -+ -+ seq_printf(seq, "24hr\t\t: yes\n"); -+ -+ if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0) -+ seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim); -+ -+ if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0) -+ seq_printf(seq, "analog_trim\t: %d.%02d pF\n", -+ atrim / 1000, atrim % 1000); -+ return 0; -+} -+ -+static struct rtc_class_ops x1205_rtc_ops = { -+ .proc = x1205_rtc_proc, -+ .read_time = x1205_rtc_read_time, -+ .set_time = x1205_rtc_set_time, -+ .read_alarm = x1205_rtc_read_alarm, -+ .set_alarm = x1205_rtc_set_alarm, -+}; -+ -+static ssize_t x1205_sysfs_show_atrim(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int atrim; -+ -+ if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0) -+ return sprintf(buf, "%d.%02d pF\n", -+ atrim / 1000, atrim % 1000); -+ return 0; -+} -+static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL); -+ -+static ssize_t x1205_sysfs_show_dtrim(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int dtrim; -+ -+ if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0) -+ return sprintf(buf, "%d ppm\n", dtrim); -+ -+ return 0; -+} -+static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); -+ -+static int x1205_attach(struct i2c_adapter *adapter) -+{ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ return i2c_probe(adapter, &addr_data, x1205_probe); -+} -+ -+static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) -+{ -+ int err = 0; -+ unsigned char sr; -+ struct i2c_client *client; -+ struct rtc_device *rtc; -+ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ /* I2C client */ -+ client->addr = address; -+ client->driver = &x1205_driver; -+ client->adapter = adapter; -+ -+ strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE); -+ -+ /* Verify the chip is really an X1205 */ -+ if (kind < 0) { -+ if (x1205_validate_client(client) < 0) { -+ err = -ENODEV; -+ goto exit_kfree; -+ } -+ } -+ -+ /* Inform the i2c layer */ -+ if ((err = i2c_attach_client(client))) -+ goto exit_kfree; -+ -+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -+ -+ rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, -+ &x1205_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ err = PTR_ERR(rtc); -+ dev_err(&client->dev, -+ "unable to register the class device\n"); -+ goto exit_detach; -+ } -+ -+ i2c_set_clientdata(client, rtc); -+ -+ /* Check for power failures and eventualy enable the osc */ -+ if ((err = x1205_get_status(client, &sr)) == 0) { -+ if (sr & X1205_SR_RTCF) { -+ dev_err(&client->dev, -+ "power failure detected, " -+ "please set the clock\n"); -+ udelay(50); -+ x1205_fix_osc(client); -+ } -+ } -+ else -+ dev_err(&client->dev, "couldn't read status\n"); -+ -+ device_create_file(&client->dev, &dev_attr_atrim); -+ device_create_file(&client->dev, &dev_attr_dtrim); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+ -+exit_kfree: -+ kfree(client); -+ -+exit: -+ return err; -+} -+ -+static int x1205_detach(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_device *rtc = i2c_get_clientdata(client); -+ -+ dev_dbg(&client->dev, "%s\n", __FUNCTION__); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ if ((err = i2c_detach_client(client))) -+ return err; -+ -+ kfree(client); -+ -+ return 0; -+} -+ -+static int __init x1205_init(void) -+{ -+ return i2c_add_driver(&x1205_driver); -+} -+ -+static void __exit x1205_exit(void) -+{ -+ i2c_del_driver(&x1205_driver); -+} -+ -+MODULE_AUTHOR( -+ "Karen Spearel <kas111 at gmail dot com>, " -+ "Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(x1205_init); -+module_exit(x1205_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-test.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,205 @@ -+/* -+ * An RTC test device/driver -+ * Copyright (C) 2005 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/module.h> -+#include <linux/err.h> -+#include <linux/rtc.h> -+#include <linux/platform_device.h> -+ -+static struct platform_device *test0 = NULL, *test1 = NULL; -+ -+static int test_rtc_read_alarm(struct device *dev, -+ struct rtc_wkalrm *alrm) -+{ -+ return 0; -+} -+ -+static int test_rtc_set_alarm(struct device *dev, -+ struct rtc_wkalrm *alrm) -+{ -+ return 0; -+} -+ -+static int test_rtc_read_time(struct device *dev, -+ struct rtc_time *tm) -+{ -+ rtc_time_to_tm(get_seconds(), tm); -+ return 0; -+} -+ -+static int test_rtc_set_time(struct device *dev, -+ struct rtc_time *tm) -+{ -+ return 0; -+} -+ -+static int test_rtc_set_mmss(struct device *dev, unsigned long secs) -+{ -+ return 0; -+} -+ -+static int test_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ struct platform_device *plat_dev = to_platform_device(dev); -+ -+ seq_printf(seq, "24hr\t\t: yes\n"); -+ seq_printf(seq, "test\t\t: yes\n"); -+ seq_printf(seq, "id\t\t: %d\n", plat_dev->id); -+ -+ return 0; -+} -+ -+static int test_rtc_ioctl(struct device *dev, unsigned int cmd, -+ unsigned long arg) -+{ -+ /* We do support interrupts, they're generated -+ * using the sysfs interface. -+ */ -+ switch (cmd) { -+ case RTC_PIE_ON: -+ case RTC_PIE_OFF: -+ case RTC_UIE_ON: -+ case RTC_UIE_OFF: -+ case RTC_AIE_ON: -+ case RTC_AIE_OFF: -+ return 0; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+static struct rtc_class_ops test_rtc_ops = { -+ .proc = test_rtc_proc, -+ .read_time = test_rtc_read_time, -+ .set_time = test_rtc_set_time, -+ .read_alarm = test_rtc_read_alarm, -+ .set_alarm = test_rtc_set_alarm, -+ .set_mmss = test_rtc_set_mmss, -+ .ioctl = test_rtc_ioctl, -+}; -+ -+static ssize_t test_irq_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "%d\n", 42); -+} -+static ssize_t test_irq_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int retval; -+ struct platform_device *plat_dev = to_platform_device(dev); -+ struct rtc_device *rtc = platform_get_drvdata(plat_dev); -+ -+ retval = count; -+ if (strncmp(buf, "tick", 4) == 0) -+ rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); -+ else if (strncmp(buf, "alarm", 5) == 0) -+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); -+ else if (strncmp(buf, "update", 6) == 0) -+ rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); -+ else -+ retval = -EINVAL; -+ -+ return retval; -+} -+static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); -+ -+static int test_probe(struct platform_device *plat_dev) -+{ -+ int err; -+ struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, -+ &test_rtc_ops, THIS_MODULE); -+ if (IS_ERR(rtc)) { -+ err = PTR_ERR(rtc); -+ dev_err(&plat_dev->dev, -+ "unable to register the class device\n"); -+ return err; -+ } -+ device_create_file(&plat_dev->dev, &dev_attr_irq); -+ -+ platform_set_drvdata(plat_dev, rtc); -+ -+ return 0; -+} -+ -+static int __devexit test_remove(struct platform_device *plat_dev) -+{ -+ struct rtc_device *rtc = platform_get_drvdata(plat_dev); -+ -+ rtc_device_unregister(rtc); -+ device_remove_file(&plat_dev->dev, &dev_attr_irq); -+ -+ return 0; -+} -+ -+static struct platform_driver test_drv = { -+ .probe = test_probe, -+ .remove = __devexit_p(test_remove), -+ .driver = { -+ .name = "rtc-test", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init test_init(void) -+{ -+ int err; -+ -+ if ((err = platform_driver_register(&test_drv))) -+ return err; -+ -+ if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { -+ err = -ENOMEM; -+ goto exit_driver_unregister; -+ } -+ -+ if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { -+ err = -ENOMEM; -+ goto exit_free_test0; -+ } -+ -+ if ((err = platform_device_add(test0))) -+ goto exit_free_test1; -+ -+ if ((err = platform_device_add(test1))) -+ goto exit_device_unregister; -+ -+ return 0; -+ -+exit_device_unregister: -+ platform_device_unregister(test0); -+ -+exit_free_test1: -+ platform_device_put(test1); -+ -+exit_free_test0: -+ platform_device_put(test0); -+ -+exit_driver_unregister: -+ platform_driver_unregister(&test_drv); -+ return err; -+} -+ -+static void __exit test_exit(void) -+{ -+ platform_device_unregister(test0); -+ platform_device_unregister(test1); -+ platform_driver_unregister(&test_drv); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("RTC test driver/device"); -+MODULE_LICENSE("GPL"); -+ -+module_init(test_init); -+module_exit(test_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-ds1672.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,233 @@ -+/* -+ * An rtc/i2c driver for the Dallas DS1672 -+ * Copyright 2005 Alessandro Zummo -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/module.h> -+#include <linux/i2c.h> -+#include <linux/rtc.h> -+ -+#define DRV_VERSION "0.2" -+ -+/* Addresses to scan: none. This chip cannot be detected. */ -+static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD; -+ -+/* Registers */ -+ -+#define DS1672_REG_CNT_BASE 0 -+#define DS1672_REG_CONTROL 4 -+#define DS1672_REG_TRICKLE 5 -+ -+ -+/* Prototypes */ -+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); -+ -+/* -+ * In the routines that deal directly with the ds1672 hardware, we use -+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch -+ * Epoch is initialized as 2000. Time is set to UTC. -+ */ -+static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ unsigned long time; -+ unsigned char addr = DS1672_REG_CNT_BASE; -+ unsigned char buf[4]; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 1, &addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 4, buf }, /* read date */ -+ }; -+ -+ /* read date registers */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ dev_dbg(&client->dev, -+ "%s: raw read data - counters=%02x,%02x,%02x,%02x\n" -+ __FUNCTION__, -+ buf[0], buf[1], buf[2], buf[3]); -+ -+ time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; -+ -+ rtc_time_to_tm(time, tm); -+ -+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ return 0; -+} -+ -+static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) -+{ -+ int xfer; -+ unsigned char buf[5]; -+ -+ buf[0] = DS1672_REG_CNT_BASE; -+ buf[1] = secs & 0x000000FF; -+ buf[2] = (secs & 0x0000FF00) >> 8; -+ buf[3] = (secs & 0x00FF0000) >> 16; -+ buf[4] = (secs & 0xFF000000) >> 24; -+ -+ xfer = i2c_master_send(client, buf, 5); -+ if (xfer != 5) { -+ dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ unsigned long secs; -+ -+ dev_dbg(&client->dev, -+ "%s: secs=%d, mins=%d, hours=%d, ", -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ rtc_tm_to_time(tm, &secs); -+ -+ return ds1672_set_mmss(client, secs); -+} -+ -+static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ return ds1672_get_datetime(to_i2c_client(dev), tm); -+} -+ -+static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ return ds1672_set_datetime(to_i2c_client(dev), tm); -+} -+ -+static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) -+{ -+ return ds1672_set_mmss(to_i2c_client(dev), secs); -+} -+ -+static struct rtc_class_ops ds1672_rtc_ops = { -+ .read_time = ds1672_rtc_read_time, -+ .set_time = ds1672_rtc_set_time, -+ .set_mmss = ds1672_rtc_set_mmss, -+}; -+ -+static int ds1672_attach(struct i2c_adapter *adapter) -+{ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ return i2c_probe(adapter, &addr_data, ds1672_probe); -+} -+ -+static int ds1672_detach(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_device *rtc = i2c_get_clientdata(client); -+ -+ dev_dbg(&client->dev, "%s\n", __FUNCTION__); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ if ((err = i2c_detach_client(client))) -+ return err; -+ -+ kfree(client); -+ -+ return 0; -+} -+ -+static struct i2c_driver ds1672_driver = { -+ .driver = { -+ .name = "ds1672", -+ }, -+ .attach_adapter = &ds1672_attach, -+ .detach_client = &ds1672_detach, -+}; -+ -+static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) -+{ -+ int err = 0; -+ struct i2c_client *client; -+ struct rtc_device *rtc; -+ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ /* I2C client */ -+ client->addr = address; -+ client->driver = &ds1672_driver; -+ client->adapter = adapter; -+ -+ strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); -+ -+ /* Inform the i2c layer */ -+ if ((err = i2c_attach_client(client))) -+ goto exit_kfree; -+ -+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -+ -+ rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, -+ &ds1672_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ err = PTR_ERR(rtc); -+ dev_err(&client->dev, -+ "unable to register the class device\n"); -+ goto exit_detach; -+ } -+ -+ i2c_set_clientdata(client, rtc); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+ -+exit_kfree: -+ kfree(client); -+ -+exit: -+ return err; -+} -+ -+static int __init ds1672_init(void) -+{ -+ return i2c_add_driver(&ds1672_driver); -+} -+ -+static void __exit ds1672_exit(void) -+{ -+ i2c_del_driver(&ds1672_driver); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ds1672_init); -+module_exit(ds1672_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-pcf8563.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,355 @@ -+/* -+ * An I2C driver for the Philips PCF8563 RTC -+ * Copyright 2005-06 Tower Technologies -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ * based on the other drivers in this same directory. -+ * -+ * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/i2c.h> -+#include <linux/bcd.h> -+#include <linux/rtc.h> -+ -+#define DRV_VERSION "0.4.2" -+ -+/* Addresses to scan: none -+ * This chip cannot be reliably autodetected. An empty eeprom -+ * located at 0x51 will pass the validation routine due to -+ * the way the registers are implemented. -+ */ -+static unsigned short normal_i2c[] = { I2C_CLIENT_END }; -+ -+/* Module parameters */ -+I2C_CLIENT_INSMOD; -+ -+#define PCF8563_REG_ST1 0x00 /* status */ -+#define PCF8563_REG_ST2 0x01 -+ -+#define PCF8563_REG_SC 0x02 /* datetime */ -+#define PCF8563_REG_MN 0x03 -+#define PCF8563_REG_HR 0x04 -+#define PCF8563_REG_DM 0x05 -+#define PCF8563_REG_DW 0x06 -+#define PCF8563_REG_MO 0x07 -+#define PCF8563_REG_YR 0x08 -+ -+#define PCF8563_REG_AMN 0x09 /* alarm */ -+#define PCF8563_REG_AHR 0x0A -+#define PCF8563_REG_ADM 0x0B -+#define PCF8563_REG_ADW 0x0C -+ -+#define PCF8563_REG_CLKO 0x0D /* clock out */ -+#define PCF8563_REG_TMRC 0x0E /* timer control */ -+#define PCF8563_REG_TMR 0x0F /* timer */ -+ -+#define PCF8563_SC_LV 0x80 /* low voltage */ -+#define PCF8563_MO_C 0x80 /* century */ -+ -+/* Prototypes */ -+static int pcf8563_attach(struct i2c_adapter *adapter); -+static int pcf8563_detach(struct i2c_client *client); -+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); -+ -+static struct i2c_driver pcf8563_driver = { -+ .driver = { -+ .name = "pcf8563", -+ }, -+ .attach_adapter = &pcf8563_attach, -+ .detach_client = &pcf8563_detach, -+}; -+ -+/* -+ * In the routines that deal directly with the pcf8563 hardware, we use -+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. -+ */ -+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ unsigned char buf[13] = { PCF8563_REG_ST1 }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 1, buf }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 13, buf }, /* read status + date */ -+ }; -+ -+ /* read registers */ -+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) -+ dev_info(&client->dev, -+ "low voltage detected, date/time is not reliable.\n"); -+ -+ dev_dbg(&client->dev, -+ "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " -+ "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", -+ __FUNCTION__, -+ buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7], -+ buf[8]); -+ -+ -+ tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F); -+ tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F); -+ tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ -+ tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); -+ tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; -+ tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ -+ tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) -+ + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0); -+ -+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ /* the clock can give out invalid datetime, but we cannot return -+ * -EINVAL otherwise hwclock will refuse to set the time on bootup. -+ */ -+ if (rtc_valid_tm(tm) < 0) -+ dev_err(&client->dev, "retrieved date/time is not valid.\n"); -+ -+ return 0; -+} -+ -+static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ int i, err; -+ unsigned char buf[9]; -+ -+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ /* hours, minutes and seconds */ -+ buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec); -+ buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min); -+ buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour); -+ -+ buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday); -+ -+ /* month, 1 - 12 */ -+ buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1); -+ -+ /* year and century */ -+ buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); -+ if (tm->tm_year / 100) -+ buf[PCF8563_REG_MO] |= PCF8563_MO_C; -+ -+ buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; -+ -+ /* write register's data */ -+ for (i = 0; i < 7; i++) { -+ unsigned char data[2] = { PCF8563_REG_SC + i, -+ buf[PCF8563_REG_SC + i] }; -+ -+ err = i2c_master_send(client, data, sizeof(data)); -+ if (err != sizeof(data)) { -+ dev_err(&client->dev, -+ "%s: err=%d addr=%02x, data=%02x\n", -+ __FUNCTION__, err, data[0], data[1]); -+ return -EIO; -+ } -+ }; -+ -+ return 0; -+} -+ -+struct pcf8563_limit -+{ -+ unsigned char reg; -+ unsigned char mask; -+ unsigned char min; -+ unsigned char max; -+}; -+ -+static int pcf8563_validate_client(struct i2c_client *client) -+{ -+ int i; -+ -+ static const struct pcf8563_limit pattern[] = { -+ /* register, mask, min, max */ -+ { PCF8563_REG_SC, 0x7F, 0, 59 }, -+ { PCF8563_REG_MN, 0x7F, 0, 59 }, -+ { PCF8563_REG_HR, 0x3F, 0, 23 }, -+ { PCF8563_REG_DM, 0x3F, 0, 31 }, -+ { PCF8563_REG_MO, 0x1F, 0, 12 }, -+ }; -+ -+ /* check limits (only registers with bcd values) */ -+ for (i = 0; i < ARRAY_SIZE(pattern); i++) { -+ int xfer; -+ unsigned char value; -+ unsigned char buf = pattern[i].reg; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 1, &buf }, -+ { client->addr, I2C_M_RD, 1, &buf }, -+ }; -+ -+ xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); -+ -+ if (xfer != ARRAY_SIZE(msgs)) { -+ dev_err(&client->adapter->dev, -+ "%s: could not read register 0x%02X\n", -+ __FUNCTION__, pattern[i].reg); -+ -+ return -EIO; -+ } -+ -+ value = BCD2BIN(buf & pattern[i].mask); -+ -+ if (value > pattern[i].max || -+ value < pattern[i].min) { -+ dev_dbg(&client->adapter->dev, -+ "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " -+ "max=%d, value=%d, raw=0x%02X\n", -+ __FUNCTION__, i, pattern[i].reg, pattern[i].mask, -+ pattern[i].min, pattern[i].max, -+ value, buf); -+ -+ return -ENODEV; -+ } -+ } -+ -+ return 0; -+} -+ -+static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ return pcf8563_get_datetime(to_i2c_client(dev), tm); -+} -+ -+static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ return pcf8563_set_datetime(to_i2c_client(dev), tm); -+} -+ -+static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ seq_printf(seq, "24hr\t\t: yes\n"); -+ return 0; -+} -+ -+static struct rtc_class_ops pcf8563_rtc_ops = { -+ .proc = pcf8563_rtc_proc, -+ .read_time = pcf8563_rtc_read_time, -+ .set_time = pcf8563_rtc_set_time, -+}; -+ -+static int pcf8563_attach(struct i2c_adapter *adapter) -+{ -+ return i2c_probe(adapter, &addr_data, pcf8563_probe); -+} -+ -+static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) -+{ -+ struct i2c_client *client; -+ struct rtc_device *rtc; -+ -+ int err = 0; -+ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ client->addr = address; -+ client->driver = &pcf8563_driver; -+ client->adapter = adapter; -+ -+ strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE); -+ -+ /* Verify the chip is really an PCF8563 */ -+ if (kind < 0) { -+ if (pcf8563_validate_client(client) < 0) { -+ err = -ENODEV; -+ goto exit_kfree; -+ } -+ } -+ -+ /* Inform the i2c layer */ -+ if ((err = i2c_attach_client(client))) -+ goto exit_kfree; -+ -+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -+ -+ rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev, -+ &pcf8563_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ err = PTR_ERR(rtc); -+ dev_err(&client->dev, -+ "unable to register the class device\n"); -+ goto exit_detach; -+ } -+ -+ i2c_set_clientdata(client, rtc); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+ -+exit_kfree: -+ kfree(client); -+ -+exit: -+ return err; -+} -+ -+static int pcf8563_detach(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_device *rtc = i2c_get_clientdata(client); -+ -+ dev_dbg(&client->dev, "%s\n", __FUNCTION__); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ if ((err = i2c_detach_client(client))) -+ return err; -+ -+ kfree(client); -+ -+ return 0; -+} -+ -+static int __init pcf8563_init(void) -+{ -+ return i2c_add_driver(&pcf8563_driver); -+} -+ -+static void __exit pcf8563_exit(void) -+{ -+ i2c_del_driver(&pcf8563_driver); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(pcf8563_init); -+module_exit(pcf8563_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-rs5c372.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,295 @@ -+/* -+ * An I2C driver for the Ricoh RS5C372 RTC -+ * -+ * Copyright (C) 2005 Pavel Mironchik pmironchik@optifacio.net -+ * Copyright (C) 2006 Tower Technologies -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/i2c.h> -+#include <linux/rtc.h> -+#include <linux/bcd.h> -+ -+#define DRV_VERSION "0.2" -+ -+/* Addresses to scan */ -+static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD; -+ -+#define RS5C372_REG_SECS 0 -+#define RS5C372_REG_MINS 1 -+#define RS5C372_REG_HOURS 2 -+#define RS5C372_REG_WDAY 3 -+#define RS5C372_REG_DAY 4 -+#define RS5C372_REG_MONTH 5 -+#define RS5C372_REG_YEAR 6 -+#define RS5C372_REG_TRIM 7 -+ -+#define RS5C372_TRIM_XSL 0x80 -+#define RS5C372_TRIM_MASK 0x7F -+ -+#define RS5C372_REG_BASE 0 -+ -+static int rs5c372_attach(struct i2c_adapter *adapter); -+static int rs5c372_detach(struct i2c_client *client); -+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind); -+ -+static struct i2c_driver rs5c372_driver = { -+ .driver = { -+ .name = "rs5c372", -+ }, -+ .attach_adapter = &rs5c372_attach, -+ .detach_client = &rs5c372_detach, -+}; -+ -+static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ unsigned char buf[7] = { RS5C372_REG_BASE }; -+ -+ /* this implements the 1st reading method, according -+ * to the datasheet. buf[0] is initialized with -+ * address ptr and transmission format register. -+ */ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 1, buf }, -+ { client->addr, I2C_M_RD, 7, buf }, -+ }; -+ -+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f); -+ tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f); -+ tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f); -+ tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07); -+ tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f); -+ -+ /* tm->tm_mon is zero-based */ -+ tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1; -+ -+ /* year is 1900 + tm->tm_year */ -+ tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100; -+ -+ dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ return 0; -+} -+ -+static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) -+{ -+ unsigned char buf[8] = { RS5C372_REG_BASE }; -+ -+ dev_dbg(&client->dev, -+ "%s: secs=%d, mins=%d, hours=%d ", -+ "mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ buf[1] = BIN2BCD(tm->tm_sec); -+ buf[2] = BIN2BCD(tm->tm_min); -+ buf[3] = BIN2BCD(tm->tm_hour); -+ buf[4] = BIN2BCD(tm->tm_wday); -+ buf[5] = BIN2BCD(tm->tm_mday); -+ buf[6] = BIN2BCD(tm->tm_mon + 1); -+ buf[7] = BIN2BCD(tm->tm_year - 100); -+ -+ if ((i2c_master_send(client, buf, 8)) != 8) { -+ dev_err(&client->dev, "%s: write error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) -+{ -+ unsigned char buf = RS5C372_REG_TRIM; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 1, &buf }, -+ { client->addr, I2C_M_RD, 1, &buf }, -+ }; -+ -+ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, trim); -+ -+ if (osc) -+ *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; -+ -+ if (trim) -+ *trim = buf & RS5C372_TRIM_MASK; -+ -+ return 0; -+} -+ -+static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ return rs5c372_get_datetime(to_i2c_client(dev), tm); -+} -+ -+static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ return rs5c372_set_datetime(to_i2c_client(dev), tm); -+} -+ -+static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ int err, osc, trim; -+ -+ seq_printf(seq, "24hr\t\t: yes\n"); -+ -+ if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) { -+ seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000); -+ seq_printf(seq, "trim\t: %d\n", trim); -+ } -+ -+ return 0; -+} -+ -+static struct rtc_class_ops rs5c372_rtc_ops = { -+ .proc = rs5c372_rtc_proc, -+ .read_time = rs5c372_rtc_read_time, -+ .set_time = rs5c372_rtc_set_time, -+}; -+ -+static ssize_t rs5c372_sysfs_show_trim(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int trim; -+ -+ if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0) -+ return sprintf(buf, "0x%2x\n", trim); -+ -+ return 0; -+} -+static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL); -+ -+static ssize_t rs5c372_sysfs_show_osc(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int osc; -+ -+ if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0) -+ return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); -+ -+ return 0; -+} -+static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL); -+ -+static int rs5c372_attach(struct i2c_adapter *adapter) -+{ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ return i2c_probe(adapter, &addr_data, rs5c372_probe); -+} -+ -+static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) -+{ -+ int err = 0; -+ struct i2c_client *client; -+ struct rtc_device *rtc; -+ -+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ /* I2C client */ -+ client->addr = address; -+ client->driver = &rs5c372_driver; -+ client->adapter = adapter; -+ -+ strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE); -+ -+ /* Inform the i2c layer */ -+ if ((err = i2c_attach_client(client))) -+ goto exit_kfree; -+ -+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -+ -+ rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev, -+ &rs5c372_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ err = PTR_ERR(rtc); -+ dev_err(&client->dev, -+ "unable to register the class device\n"); -+ goto exit_detach; -+ } -+ -+ i2c_set_clientdata(client, rtc); -+ -+ device_create_file(&client->dev, &dev_attr_trim); -+ device_create_file(&client->dev, &dev_attr_osc); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+ -+exit_kfree: -+ kfree(client); -+ -+exit: -+ return err; -+} -+ -+static int rs5c372_detach(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_device *rtc = i2c_get_clientdata(client); -+ -+ dev_dbg(&client->dev, "%s\n", __FUNCTION__); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ if ((err = i2c_detach_client(client))) -+ return err; -+ -+ kfree(client); -+ -+ return 0; -+} -+ -+static __init int rs5c372_init(void) -+{ -+ return i2c_add_driver(&rs5c372_driver); -+} -+ -+static __exit void rs5c372_exit(void) -+{ -+ i2c_del_driver(&rs5c372_driver); -+} -+ -+module_init(rs5c372_init); -+module_exit(rs5c372_exit); -+ -+MODULE_AUTHOR( -+ "Pavel Mironchik <pmironchik@optifacio.net>, " -+ "Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-ep93xx.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,163 @@ -+/* -+ * A driver for the RTC embedded in the Cirrus Logic EP93XX processors -+ * Copyright (c) 2006 Tower Technologies -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/module.h> -+#include <linux/rtc.h> -+#include <linux/platform_device.h> -+#include <asm/hardware.h> -+ -+#define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) -+#define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) -+#define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C) -+#define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108) -+ -+#define DRV_VERSION "0.2" -+ -+static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload, -+ unsigned short *delete) -+{ -+ unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP); -+ -+ if (preload) -+ *preload = comp & 0xffff; -+ -+ if (delete) -+ *delete = (comp >> 16) & 0x1f; -+ -+ return 0; -+} -+ -+static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ unsigned long time = __raw_readl(EP93XX_RTC_DATA); -+ -+ rtc_time_to_tm(time, tm); -+ return 0; -+} -+ -+static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) -+{ -+ __raw_writel(secs + 1, EP93XX_RTC_LOAD); -+ return 0; -+} -+ -+static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ int err; -+ unsigned long secs; -+ -+ err = rtc_tm_to_time(tm, &secs); -+ if (err != 0) -+ return err; -+ -+ return ep93xx_rtc_set_mmss(dev, secs); -+} -+ -+static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ unsigned short preload, delete; -+ -+ ep93xx_get_swcomp(dev, &preload, &delete); -+ -+ seq_printf(seq, "24hr\t\t: yes\n"); -+ seq_printf(seq, "preload\t\t: %d\n", preload); -+ seq_printf(seq, "delete\t\t: %d\n", delete); -+ -+ return 0; -+} -+ -+static struct rtc_class_ops ep93xx_rtc_ops = { -+ .read_time = ep93xx_rtc_read_time, -+ .set_time = ep93xx_rtc_set_time, -+ .set_mmss = ep93xx_rtc_set_mmss, -+ .proc = ep93xx_rtc_proc, -+}; -+ -+static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ unsigned short preload; -+ -+ ep93xx_get_swcomp(dev, &preload, NULL); -+ -+ return sprintf(buf, "%d\n", preload); -+} -+static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL); -+ -+static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ unsigned short delete; -+ -+ ep93xx_get_swcomp(dev, NULL, &delete); -+ -+ return sprintf(buf, "%d\n", delete); -+} -+static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL); -+ -+ -+static int __devinit ep93xx_rtc_probe(struct platform_device *dev) -+{ -+ struct rtc_device *rtc = rtc_device_register("ep93xx", -+ &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ dev_err(&dev->dev, "unable to register\n"); -+ return PTR_ERR(rtc); -+ } -+ -+ platform_set_drvdata(dev, rtc); -+ -+ device_create_file(&dev->dev, &dev_attr_comp_preload); -+ device_create_file(&dev->dev, &dev_attr_comp_delete); -+ -+ return 0; -+} -+ -+static int __devexit ep93xx_rtc_remove(struct platform_device *dev) -+{ -+ struct rtc_device *rtc = platform_get_drvdata(dev); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ platform_set_drvdata(dev, NULL); -+ -+ return 0; -+} -+ -+static struct platform_driver ep93xx_rtc_platform_driver = { -+ .driver = { -+ .name = "ep93xx-rtc", -+ .owner = THIS_MODULE, -+ }, -+ .probe = ep93xx_rtc_probe, -+ .remove = __devexit_p(ep93xx_rtc_remove), -+}; -+ -+static int __init ep93xx_rtc_init(void) -+{ -+ return platform_driver_register(&ep93xx_rtc_platform_driver); -+} -+ -+static void __exit ep93xx_rtc_exit(void) -+{ -+ platform_driver_unregister(&ep93xx_rtc_platform_driver); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("EP93XX RTC driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ep93xx_rtc_init); -+module_exit(ep93xx_rtc_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/rtc/rtc-sa1100.c 2006-03-08 01:59:26.000000000 +0100 -@@ -0,0 +1,392 @@ -+/* -+ * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx -+ * -+ * Copyright (c) 2000 Nils Faerber -+ * -+ * Based on rtc.c by Paul Gortmaker -+ * -+ * Original Driver by Nils Faerber <nils@kernelconcepts.de> -+ * -+ * Modifications from: -+ * CIH <cih@coventive.com> -+ * Nicolas Pitre <nico@cam.org> -+ * Andrew Christian <andrew.christian@hp.com> -+ * -+ * Converted to the RTC subsystem and Driver Model -+ * by Richard Purdie <rpurdie@rpsys.net> -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include <linux/platform_device.h> -+#include <linux/module.h> -+#include <linux/rtc.h> -+#include <linux/init.h> -+#include <linux/fs.h> -+#include <linux/interrupt.h> -+#include <linux/string.h> -+#include <linux/pm.h> -+ -+#include <asm/bitops.h> -+#include <asm/hardware.h> -+#include <asm/irq.h> -+#include <asm/rtc.h> -+ -+#ifdef CONFIG_ARCH_PXA -+#include <asm/arch/pxa-regs.h> -+#endif -+ -+#define TIMER_FREQ CLOCK_TICK_RATE -+#define RTC_DEF_DIVIDER 32768 - 1 -+#define RTC_DEF_TRIM 0 -+ -+static unsigned long rtc_freq = 1024; -+static struct rtc_time rtc_alarm; -+static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED; -+ -+static int rtc_update_alarm(struct rtc_time *alrm) -+{ -+ struct rtc_time alarm_tm, now_tm; -+ unsigned long now, time; -+ int ret; -+ -+ do { -+ now = RCNR; -+ rtc_time_to_tm(now, &now_tm); -+ rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); -+ ret = rtc_tm_to_time(&alarm_tm, &time); -+ if (ret != 0) -+ break; -+ -+ RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); -+ RTAR = time; -+ } while (now != RCNR); -+ -+ return ret; -+} -+ -+static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id, -+ struct pt_regs *regs) -+{ -+ struct platform_device *pdev = to_platform_device(dev_id); -+ struct rtc_device *rtc = platform_get_drvdata(pdev); -+ unsigned int rtsr; -+ unsigned long events = 0; -+ -+ spin_lock(&sa1100_rtc_lock); -+ -+ rtsr = RTSR; -+ /* clear interrupt sources */ -+ RTSR = 0; -+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); -+ -+ /* clear alarm interrupt if it has occurred */ -+ if (rtsr & RTSR_AL) -+ rtsr &= ~RTSR_ALE; -+ RTSR = rtsr & (RTSR_ALE | RTSR_HZE); -+ -+ /* update irq data & counter */ -+ if (rtsr & RTSR_AL) -+ events |= RTC_AF | RTC_IRQF; -+ if (rtsr & RTSR_HZ) -+ events |= RTC_UF | RTC_IRQF; -+ -+ rtc_update_irq(&rtc->class_dev, 1, events); -+ -+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) -+ rtc_update_alarm(&rtc_alarm); -+ -+ spin_unlock(&sa1100_rtc_lock); -+ -+ return IRQ_HANDLED; -+} -+ -+static int rtc_timer1_count; -+ -+static irqreturn_t timer1_interrupt(int irq, void *dev_id, -+ struct pt_regs *regs) -+{ -+ struct platform_device *pdev = to_platform_device(dev_id); -+ struct rtc_device *rtc = platform_get_drvdata(pdev); -+ -+ /* -+ * If we match for the first time, rtc_timer1_count will be 1. -+ * Otherwise, we wrapped around (very unlikely but -+ * still possible) so compute the amount of missed periods. -+ * The match reg is updated only when the data is actually retrieved -+ * to avoid unnecessary interrupts. -+ */ -+ OSSR = OSSR_M1; /* clear match on timer1 */ -+ -+ rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF); -+ -+ if (rtc_timer1_count == 1) -+ rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); -+ -+ return IRQ_HANDLED; -+} -+ -+static int sa1100_rtc_read_callback(struct device *dev, int data) -+{ -+ if (data & RTC_PF) { -+ /* interpolate missed periods and set match for the next */ -+ unsigned long period = TIMER_FREQ/rtc_freq; -+ unsigned long oscr = OSCR; -+ unsigned long osmr1 = OSMR1; -+ unsigned long missed = (oscr - osmr1)/period; -+ data += missed << 8; -+ OSSR = OSSR_M1; /* clear match on timer 1 */ -+ OSMR1 = osmr1 + (missed + 1)*period; -+ /* Ensure we didn't miss another match in the mean time. -+ * Here we compare (match - OSCR) 8 instead of 0 -- -+ * see comment in pxa_timer_interrupt() for explanation. -+ */ -+ while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { -+ data += 0x100; -+ OSSR = OSSR_M1; /* clear match on timer 1 */ -+ OSMR1 = osmr1 + period; -+ } -+ } -+ return data; -+} -+ -+static int sa1100_rtc_open(struct device *dev) -+{ -+ int ret; -+ -+ ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, -+ "rtc 1Hz", dev); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); -+ goto fail_ui; -+ } -+ ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, -+ "rtc Alrm", dev); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); -+ goto fail_ai; -+ } -+ ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, -+ "rtc timer", dev); -+ if (ret) { -+ printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); -+ goto fail_pi; -+ } -+ return 0; -+ -+ fail_pi: -+ free_irq(IRQ_RTCAlrm, NULL); -+ fail_ai: -+ free_irq(IRQ_RTC1Hz, NULL); -+ fail_ui: -+ return ret; -+} -+ -+static void sa1100_rtc_release(struct device *dev) -+{ -+ spin_lock_irq(&sa1100_rtc_lock); -+ RTSR = 0; -+ OIER &= ~OIER_E1; -+ OSSR = OSSR_M1; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ -+ free_irq(IRQ_OST1, dev); -+ free_irq(IRQ_RTCAlrm, dev); -+ free_irq(IRQ_RTC1Hz, dev); -+} -+ -+ -+static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, -+ unsigned long arg) -+{ -+ switch(cmd) { -+ case RTC_AIE_OFF: -+ spin_lock_irq(&sa1100_rtc_lock); -+ RTSR &= ~RTSR_ALE; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_AIE_ON: -+ spin_lock_irq(&sa1100_rtc_lock); -+ RTSR |= RTSR_ALE; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_UIE_OFF: -+ spin_lock_irq(&sa1100_rtc_lock); -+ RTSR &= ~RTSR_HZE; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_UIE_ON: -+ spin_lock_irq(&sa1100_rtc_lock); -+ RTSR |= RTSR_HZE; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_PIE_OFF: -+ spin_lock_irq(&sa1100_rtc_lock); -+ OIER &= ~OIER_E1; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_PIE_ON: -+ if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) -+ return -EACCES; -+ spin_lock_irq(&sa1100_rtc_lock); -+ OSMR1 = TIMER_FREQ/rtc_freq + OSCR; -+ OIER |= OIER_E1; -+ rtc_timer1_count = 1; -+ spin_unlock_irq(&sa1100_rtc_lock); -+ return 0; -+ case RTC_IRQP_READ: -+ return put_user(rtc_freq, (unsigned long *)arg); -+ case RTC_IRQP_SET: -+ if (arg < 1 || arg > TIMER_FREQ) -+ return -EINVAL; -+ if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) -+ return -EACCES; -+ rtc_freq = arg; -+ return 0; -+ } -+ return -EINVAL; -+} -+ -+static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ rtc_time_to_tm(RCNR, tm); -+ return 0; -+} -+ -+static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ unsigned long time; -+ int ret; -+ -+ ret = rtc_tm_to_time(tm, &time); -+ if (ret == 0) -+ RCNR = time; -+ return ret; -+} -+ -+static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); -+ alrm->pending = RTSR & RTSR_AL ? 1 : 0; -+ return 0; -+} -+ -+static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -+{ -+ int ret; -+ -+ spin_lock_irq(&sa1100_rtc_lock); -+ ret = rtc_update_alarm(&alrm->time); -+ if (ret == 0) { -+ memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time)); -+ -+ if (alrm->enabled) -+ enable_irq_wake(IRQ_RTCAlrm); -+ else -+ disable_irq_wake(IRQ_RTCAlrm); -+ } -+ spin_unlock_irq(&sa1100_rtc_lock); -+ -+ return ret; -+} -+ -+static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR); -+ seq_printf(seq, "alarm_IRQ\t: %s\n", -+ (RTSR & RTSR_ALE) ? "yes" : "no" ); -+ seq_printf(seq, "update_IRQ\t: %s\n", -+ (RTSR & RTSR_HZE) ? "yes" : "no"); -+ seq_printf(seq, "periodic_IRQ\t: %s\n", -+ (OIER & OIER_E1) ? "yes" : "no"); -+ seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); -+ -+ return 0; -+} -+ -+static struct rtc_class_ops sa1100_rtc_ops = { -+ .open = sa1100_rtc_open, -+ .read_callback = sa1100_rtc_read_callback, -+ .release = sa1100_rtc_release, -+ .ioctl = sa1100_rtc_ioctl, -+ .read_time = sa1100_rtc_read_time, -+ .set_time = sa1100_rtc_set_time, -+ .read_alarm = sa1100_rtc_read_alarm, -+ .set_alarm = sa1100_rtc_set_alarm, -+ .proc = sa1100_rtc_proc, -+}; -+ -+static int sa1100_rtc_probe(struct platform_device *pdev) -+{ -+ struct rtc_device *rtc; -+ -+ /* -+ * According to the manual we should be able to let RTTR be zero -+ * and then a default diviser for a 32.768KHz clock is used. -+ * Apparently this doesn't work, at least for my SA1110 rev 5. -+ * If the clock divider is uninitialized then reset it to the -+ * default value to get the 1Hz clock. -+ */ -+ if (RTTR == 0) { -+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); -+ printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); -+ /* The current RTC value probably doesn't make sense either */ -+ RCNR = 0; -+ } -+ -+ rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, -+ THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ dev_err(&pdev->dev, "Unable to register the RTC device\n"); -+ return PTR_ERR(rtc); -+ } -+ -+ platform_set_drvdata(pdev, rtc); -+ -+ dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n"); -+ -+ return 0; -+} -+ -+static int sa1100_rtc_remove(struct platform_device *pdev) -+{ -+ struct rtc_device *rtc = platform_get_drvdata(pdev); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ return 0; -+} -+ -+static struct platform_driver sa1100_rtc_driver = { -+ .probe = sa1100_rtc_probe, -+ .remove = sa1100_rtc_remove, -+ .driver = { -+ .name = "sa1100-rtc", -+ }, -+}; -+ -+static int __init sa1100_rtc_init(void) -+{ -+ return platform_driver_register(&sa1100_rtc_driver); -+} -+ -+static void __exit sa1100_rtc_exit(void) -+{ -+ platform_driver_unregister(&sa1100_rtc_driver); -+} -+ -+module_init(sa1100_rtc_init); -+module_exit(sa1100_rtc_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); -+MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); -+MODULE_LICENSE("GPL"); ---- linux-ixp4xx.orig/arch/arm/mach-pxa/generic.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/generic.c 2006-03-08 01:59:26.000000000 +0100 -@@ -319,6 +319,11 @@ void __init pxa_set_ficp_info(struct pxa - pxaficp_device.dev.platform_data = info; - } - -+static struct platform_device pxartc_device = { -+ .name = "sa1100-rtc", -+ .id = -1, -+}; -+ - static struct platform_device *devices[] __initdata = { - &pxamci_device, - &udc_device, -@@ -329,6 +334,7 @@ static struct platform_device *devices[] - &pxaficp_device, - &i2c_device, - &i2s_device, -+ &pxartc_device, - }; - - static int __init pxa_init(void) ---- linux-ixp4xx.orig/arch/arm/mach-sa1100/generic.c 2006-03-08 01:59:09.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-sa1100/generic.c 2006-03-08 01:59:26.000000000 +0100 -@@ -324,6 +324,11 @@ void sa11x0_set_irda_data(struct irda_pl - sa11x0ir_device.dev.platform_data = irda; - } - -+static struct platform_device sa11x0rtc_device = { -+ .name = "sa1100-rtc", -+ .id = -1, -+}; -+ - static struct platform_device *sa11x0_devices[] __initdata = { - &sa11x0udc_device, - &sa11x0uart1_device, -@@ -333,6 +338,7 @@ static struct platform_device *sa11x0_de - &sa11x0pcmcia_device, - &sa11x0fb_device, - &sa11x0mtd_device, -+ &sa11x0rtc_device, - }; - - static int __init sa1100_init(void) diff --git a/packages/linux/ixp4xx-kernel/2.6.16/45-eeprom-new-notifier.patch b/packages/linux/ixp4xx-kernel/2.6.16/45-eeprom-new-notifier.patch deleted file mode 100644 index 2de12021a5..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/45-eeprom-new-notifier.patch +++ /dev/null @@ -1,209 +0,0 @@ -Add EEPROM notifiers - -These help board level code by allowing a callback when EEPROMs are -loaded, this permits system level configuration to be loaded from the -EEPROM. This is particularly useful when the ethernet MAC ids are -stored in EEPROM and when the ethernet hardware is generic (so it -has no board level knowledge), then the MACs can be loaded into -the 'maclist' code and read out by the ethernet config. - -Signed-off-by: John Bowler <jbowler@acm.org> - ---- - drivers/i2c/chips/eeprom.c | 63 ++++++++++++++++++++++++++------------- - include/linux/eeprom.h | 71 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/notifier.h | 3 + - 3 files changed, 116 insertions(+), 21 deletions(-) - ---- linux-ixp4xx.orig/drivers/i2c/chips/eeprom.c 2006-03-27 03:03:46.000000000 +0200 -+++ linux-ixp4xx/drivers/i2c/chips/eeprom.c 2006-03-27 03:03:47.000000000 +0200 -@@ -25,7 +25,6 @@ - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -- - #include <linux/kernel.h> - #include <linux/init.h> - #include <linux/module.h> -@@ -34,6 +33,8 @@ - #include <linux/jiffies.h> - #include <linux/i2c.h> - #include <linux/mutex.h> -+#include <linux/notifier.h> -+#include <linux/eeprom.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, -@@ -42,26 +43,7 @@ static unsigned short normal_i2c[] = { 0 - /* Insmod parameters */ - I2C_CLIENT_INSMOD_1(eeprom); - -- --/* Size of EEPROM in bytes */ --#define EEPROM_SIZE 256 -- --/* possible types of eeprom devices */ --enum eeprom_nature { -- UNKNOWN, -- VAIO, --}; -- --/* Each client has this additional data */ --struct eeprom_data { -- struct i2c_client client; -- struct mutex update_lock; -- u8 valid; /* bitfield, bit!=0 if slice is valid */ -- unsigned long last_updated[8]; /* In jiffies, 8 slices */ -- u8 data[EEPROM_SIZE]; /* Register values */ -- enum eeprom_nature nature; --}; -- -+static struct notifier_block *eeprom_chain; - - static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); - static int eeprom_detach_client(struct i2c_client *client); -@@ -186,6 +168,7 @@ static int eeprom_detect(struct i2c_adap - data->valid = 0; - mutex_init(&data->update_lock); - data->nature = UNKNOWN; -+ data->attr = &eeprom_attr; - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -207,6 +190,9 @@ static int eeprom_detect(struct i2c_adap - /* create the sysfs eeprom file */ - sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); - -+ /* call the notifier chain */ -+ notifier_call_chain(&eeprom_chain, EEPROM_REGISTER, data); -+ - return 0; - - exit_kfree: -@@ -228,6 +214,41 @@ static int eeprom_detach_client(struct i - return 0; - } - -+/** -+ * register_eeprom_notifier - register a 'user' of EEPROM devices. -+ * @nb: pointer to notifier info structure -+ * -+ * Registers a callback function to be called upon detection -+ * of an EEPROM device. Detection invokes the 'add' callback -+ * with the kobj of the mutex and a bin_attribute which allows -+ * read from the EEPROM. The intention is that the notifier -+ * will be able to read system configuration from the notifier. -+ * -+ * Only EEPROMs detected *after* the addition of the notifier -+ * are notified. I.e. EEPROMs already known to the system -+ * will not be notified - add the notifier from board level -+ * code! -+ */ -+int register_eeprom_notifier(struct notifier_block *nb) -+{ -+ return notifier_chain_register(&eeprom_chain, nb); -+} -+ -+/** -+ * unregister_eeprom_notifier - unregister a 'user' of EEPROM devices. -+ * @old: pointer to notifier info structure -+ * -+ * Removes a callback function from the list of 'users' to be -+ * notified upon detection of EEPROM devices. -+ */ -+int unregister_eeprom_notifier(struct notifier_block *nb) -+{ -+ return notifier_chain_unregister(&eeprom_chain, nb); -+} -+ -+EXPORT_SYMBOL_GPL(register_eeprom_notifier); -+EXPORT_SYMBOL_GPL(unregister_eeprom_notifier); -+ - static int __init eeprom_init(void) - { - return i2c_add_driver(&eeprom_driver); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/linux/eeprom.h 2006-03-27 03:03:47.000000000 +0200 -@@ -0,0 +1,71 @@ -+#ifndef _LINUX_EEPROM_H -+#define _LINUX_EEPROM_H -+/* -+ * $Id: 45-eeprom-new-notifier.patch,v 1.2 2006/03/27 11:10:19 azummo Exp $ -+ * -+ * Copyright (C) 2006 John Bowler -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __KERNEL__ -+#error This is a kernel header -+#endif -+ -+#include <linux/list.h> -+#include <linux/kobject.h> -+#include <linux/sysfs.h> -+ -+/* Size of EEPROM in bytes */ -+#define EEPROM_SIZE 256 -+ -+/* possible types of eeprom devices */ -+enum eeprom_nature { -+ UNKNOWN, -+ VAIO, -+}; -+ -+/* Each client has this additional data */ -+struct eeprom_data { -+ struct i2c_client client; -+ struct mutex update_lock; -+ u8 valid; /* bitfield, bit!=0 if slice is valid */ -+ unsigned long last_updated[8]; /* In jiffies, 8 slices */ -+ u8 data[EEPROM_SIZE]; /* Register values */ -+ enum eeprom_nature nature; -+ struct bin_attribute *attr; -+}; -+ -+/* -+ * This is very basic. -+ * -+ * If an EEPROM is detected on the I2C bus (this only works for -+ * I2C EEPROMs) the eeprom_notifier::add method is called with -+ * both the I2C information and the kobject for the sysfs -+ * device which has been registers. It is then possible to -+ * read from the device via the bin_attribute::read method -+ * to extract configuration information. -+ * -+ * Register the notifier in the board level code, there is no -+ * need to unregister it but you can if you want (it will save -+ * a little bit or kernel memory to do so). -+ */ -+ -+extern int register_eeprom_notifier(struct notifier_block *nb); -+extern int unregister_eeprom_notifier(struct notifier_block *nb); -+ -+#endif /* _LINUX_EEPROM_H */ ---- linux-ixp4xx.orig/include/linux/notifier.h 2006-03-27 01:33:10.000000000 +0200 -+++ linux-ixp4xx/include/linux/notifier.h 2006-03-27 03:03:47.000000000 +0200 -@@ -72,5 +72,8 @@ extern int notifier_call_chain(struct no - #define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ - #define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ - -+/* eeprom notifier chain */ -+#define EEPROM_REGISTER 0x0001 -+ - #endif /* __KERNEL__ */ - #endif /* _LINUX_NOTIFIER_H */ diff --git a/packages/linux/ixp4xx-kernel/2.6.16/48-setup-byteswap-cmdline.patch b/packages/linux/ixp4xx-kernel/2.6.16/48-setup-byteswap-cmdline.patch deleted file mode 100644 index 1c2243ba35..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/48-setup-byteswap-cmdline.patch +++ /dev/null @@ -1,51 +0,0 @@ -When invoking an LE kernel from a BE boot loader or vice versa -the ATAG_CMDLINE command line will be byte swapped, other ATAGs -are fine because they are 32 bit values. - -This patch adds support for a command line option "swx " - which -must be at the start of the command line - and which is used to -detect a need to byte swap the rest of the command line. - -Signed-off-by: John Bowler <jbowler@acm.org> - - arch/arm/kernel/setup.c | 29 ++++++++++++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) - ---- linux-nslu2.orig/arch/arm/kernel/setup.c 2006-02-06 20:37:00.000000000 +0100 -+++ linux-nslu2/arch/arm/kernel/setup.c 2006-02-06 21:49:18.000000000 +0100 -@@ -660,7 +660,34 @@ __tagtable(ATAG_REVISION, parse_tag_revi - - static int __init parse_tag_cmdline(const struct tag *tag) - { -- strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE); -+ /* Check the first four bytes for "swx " (swap, but it's -+ * ok) or " xws" (command line is byte swapped) -+ */ -+ const char *cmdline = tag->u.cmdline.cmdline; -+ u32 size = tag->hdr.size; -+ -+ if (size > 0 && !memcmp(cmdline, " xws", 4)) { -+ cmdline += 4; -+ -+ if (--size > 0) { -+ const u32 *from = (const u32*)cmdline; -+ u32 *to = (u32*)default_command_line; -+ -+ if (size > COMMAND_LINE_SIZE/4) -+ size = COMMAND_LINE_SIZE/4; -+ -+ while (size-- > 0) -+ to[size] = swab32(from[size]); -+ -+ default_command_line[COMMAND_LINE_SIZE-1] = 0; -+ return 0; -+ } -+ } -+ -+ if (size > 0 && !memcmp(cmdline, "swx ", 4)) -+ cmdline += 4; -+ -+ strlcpy(default_command_line, cmdline, COMMAND_LINE_SIZE); - return 0; - } - diff --git a/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch b/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch deleted file mode 100644 index 9d0a35b3fa..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch +++ /dev/null @@ -1,378 +0,0 @@ ---- - drivers/hwmon/Kconfig | 10 + - drivers/hwmon/Makefile | 1 - drivers/hwmon/ad741x.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 351 insertions(+) - ---- linux-ixp4xx.orig/drivers/hwmon/Makefile 2006-02-19 17:45:45.000000000 +0100 -+++ linux-ixp4xx/drivers/hwmon/Makefile 2006-02-19 17:46:12.000000000 +0100 -@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_VIA686A) += via686a - obj-$(CONFIG_SENSORS_VT8231) += vt8231.o - obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o - obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o -+obj-$(CONFIG_SENSORS_AD741X) += ad741x.o - - ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) - EXTRA_CFLAGS += -DDEBUG ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/hwmon/ad741x.c 2006-02-19 17:45:59.000000000 +0100 -@@ -0,0 +1,340 @@ -+/* -+ * An hwmon driver for the Analog Devices AD7417/18 -+ * Copyright 2006 Tower Technologies -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * Based on lm75.c -+ * Copyright 1998-99 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. -+ */ -+ -+#include <linux/module.h> -+#include <linux/jiffies.h> -+#include <linux/i2c.h> -+#include <linux/hwmon.h> -+#include <linux/err.h> -+#include <linux/mutex.h> -+ -+#define DRV_VERSION "0.1" -+ -+/* straight from the datasheet */ -+#define AD741X_TEMP_MIN (-55000) -+#define AD741X_TEMP_MAX 125000 -+ -+/* Addresses to scan */ -+static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2A, 0x2B, 0x2C, -+ 0x2D, 0x2E, 0x2F, I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD; -+ -+/* AD741X registers */ -+#define AD741X_REG_TEMP 0x00 -+#define AD741X_REG_CONF 0x01 -+#define AD741X_REG_TEMP_HYST 0x02 -+#define AD741X_REG_TEMP_OS 0x03 -+#define AD741X_REG_ADC 0x04 -+#define AD741X_REG_CONF2 0x05 -+ -+#define AD741X_REG_ADC_CH(x) (x << 5) -+ -+#define AD741X_CH_TEMP AD741X_REG_ADC_CH(0) -+#define AD741X_CH_AIN1 AD741X_REG_ADC_CH(1) -+#define AD741X_CH_AIN2 AD741X_REG_ADC_CH(2) -+#define AD741X_CH_AIN3 AD741X_REG_ADC_CH(3) -+#define AD741X_CH_AIN4 AD741X_REG_ADC_CH(4) -+ -+struct ad741x_data { -+ struct i2c_client client; -+ struct class_device *class_dev; -+ struct mutex 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; -+ u16 in1; -+ u16 in2; -+ u16 in3; -+ u16 in4; -+}; -+ -+static int ad741x_attach_adapter(struct i2c_adapter *adapter); -+static int ad741x_detect(struct i2c_adapter *adapter, int address, int kind); -+static int ad741x_detach_client(struct i2c_client *client); -+ -+static struct i2c_driver ad741x_driver = { -+ .driver = { -+ .name = "ad741x", -+ }, -+ .attach_adapter = ad741x_attach_adapter, -+ .detach_client = ad741x_detach_client, -+}; -+ -+/* TEMP: 0.001C/bit (-55C to +125C) -+ * REG: (0.5C/bit, two's complement) << 7 -+ */ -+static inline u16 AD741X_TEMP_TO_REG(int temp) -+{ -+ int ntemp = SENSORS_LIMIT(temp, AD741X_TEMP_MIN, AD741X_TEMP_MAX); -+ ntemp += (ntemp < 0 ? -250 : 250); -+ return (u16)((ntemp / 500) << 7); -+} -+ -+static inline int AD741X_TEMP_FROM_REG(u16 reg) -+{ -+ /* use integer division instead of equivalent right shift to -+ * guarantee arithmetic shift and preserve the sign -+ */ -+ return ((s16)reg / 128) * 500; -+} -+ -+/* All registers are word-sized, except for the configuration registers. -+ * AD741X uses a high-byte first convention, which is exactly opposite to -+ * the usual practice. -+ */ -+static int ad741x_read(struct i2c_client *client, u8 reg) -+{ -+ if (reg == AD741X_REG_CONF || reg == AD741X_REG_CONF2) -+ return i2c_smbus_read_byte_data(client, reg); -+ else -+ return swab16(i2c_smbus_read_word_data(client, reg)); -+} -+ -+static int ad741x_write(struct i2c_client *client, u8 reg, u16 value) -+{ -+ if (reg == AD741X_REG_CONF || reg == AD741X_REG_CONF2) -+ return i2c_smbus_write_byte_data(client, reg, value); -+ else -+ return i2c_smbus_write_word_data(client, reg, swab16(value)); -+} -+ -+static void ad741x_init_client(struct i2c_client *client) -+{ -+ /* Enable if in shutdown mode */ -+ int reg = ad741x_read(client, AD741X_REG_CONF); -+ if (reg >= 0 && (reg & 0x01)) -+ ad741x_write(client, AD741X_REG_CONF, reg & 0xfe); -+} -+ -+static struct ad741x_data *ad741x_update_device(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct ad741x_data *data = i2c_get_clientdata(client); -+ -+ mutex_lock(&data->lock); -+ -+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) -+ || !data->valid) { -+ u8 cfg; -+ dev_dbg(&client->dev, "starting ad741x update\n"); -+ -+ data->temp_input = ad741x_read(client, AD741X_REG_TEMP); -+ data->temp_max = ad741x_read(client, AD741X_REG_TEMP_OS); -+ data->temp_hyst = ad741x_read(client, AD741X_REG_TEMP_HYST); -+ -+ /* read config register and clear channel bits */ -+ cfg = ad741x_read(client, AD741X_REG_CONF); -+ cfg &= 0x1F; -+ -+ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN1); -+ data->in1 = ad741x_read(client, AD741X_REG_ADC); -+ -+ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN2); -+ data->in2 = ad741x_read(client, AD741X_REG_ADC); -+ -+ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN3); -+ data->in3 = ad741x_read(client, AD741X_REG_ADC); -+ -+ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN4); -+ data->in4 = ad741x_read(client, AD741X_REG_ADC); -+ -+ /* restore old configuration value */ -+ ad741x_write(client, AD741X_REG_CONF, cfg); -+ -+ data->last_updated = jiffies; -+ data->valid = 1; -+ } -+ -+ mutex_unlock(&data->lock); -+ -+ return data; -+} -+ -+#define show(value) \ -+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct ad741x_data *data = ad741x_update_device(dev); \ -+ return sprintf(buf, "%d\n", AD741X_TEMP_FROM_REG(data->value)); \ -+} -+show(temp_max); -+show(temp_hyst); -+show(temp_input); -+ -+#define show_adc(value) \ -+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct ad741x_data *data = ad741x_update_device(dev); \ -+ return sprintf(buf, "%d\n", data->value >> 6); \ -+} -+ -+show_adc(in1); -+show_adc(in2); -+show_adc(in3); -+show_adc(in4); -+ -+#define set(value, reg) \ -+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -+{ \ -+ struct i2c_client *client = to_i2c_client(dev); \ -+ struct ad741x_data *data = i2c_get_clientdata(client); \ -+ int temp = simple_strtoul(buf, NULL, 10); \ -+ \ -+ mutex_lock(&data->lock); \ -+ data->value = AD741X_TEMP_TO_REG(temp); \ -+ ad741x_write(client, reg, data->value); \ -+ mutex_unlock(&data->lock); \ -+ return count; \ -+} -+set(temp_max, AD741X_REG_TEMP_OS); -+set(temp_hyst, AD741X_REG_TEMP_HYST); -+ -+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); -+static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); -+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); -+ -+static DEVICE_ATTR(in1, S_IRUGO, show_in1, NULL); -+static DEVICE_ATTR(in2, S_IRUGO, show_in2, NULL); -+static DEVICE_ATTR(in3, S_IRUGO, show_in3, NULL); -+static DEVICE_ATTR(in4, S_IRUGO, show_in4, NULL); -+ -+static int ad741x_attach_adapter(struct i2c_adapter *adapter) -+{ -+ if (!(adapter->class & I2C_CLASS_HWMON)) -+ return 0; -+ return i2c_probe(adapter, &addr_data, ad741x_detect); -+} -+ -+static int ad741x_detect(struct i2c_adapter *adapter, int address, int kind) -+{ -+ struct i2c_client *client; -+ struct ad741x_data *data; -+ int err = 0; -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | -+ I2C_FUNC_SMBUS_WORD_DATA)) -+ goto exit; -+ -+ if (!(data = kzalloc(sizeof(struct ad741x_data), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ client = &data->client; -+ client->addr = address; -+ client->adapter = adapter; -+ client->driver = &ad741x_driver; -+ client->flags = 0; -+ -+ i2c_set_clientdata(client, data); -+ -+ mutex_init(&data->lock); -+ -+ /* AD7418 has a curious behaviour on registers 6 and 7. They -+ * both always read 0xC071 and are not documented on the datasheet. -+ * We use them to detect the chip. -+ */ -+ if (kind < 0) { -+ int reg; -+ -+ reg = i2c_smbus_read_word_data(client, 0x06); -+ if (reg != 0xC071) { -+ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", 6, reg); -+ err = -ENODEV; -+ goto exit_free; -+ } -+ -+ reg = i2c_smbus_read_word_data(client, 0x07); -+ if (reg != 0xC071) { -+ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", 7, reg); -+ err = -ENODEV; -+ goto exit_free; -+ } -+ -+ reg = i2c_smbus_read_byte_data(client, AD741X_REG_CONF2); -+ -+ /* bits 0-5 must be at 0 */ -+ if (reg & 0x3F) { -+ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", -+ AD741X_REG_CONF2, reg); -+ err = -ENODEV; -+ goto exit_free; -+ } -+ } -+ -+ strlcpy(client->name, ad741x_driver.driver.name, I2C_NAME_SIZE); -+ -+ if ((err = i2c_attach_client(client))) -+ goto exit_free; -+ -+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); -+ -+ /* Initialize the AD741X chip */ -+ ad741x_init_client(client); -+ -+ /* Register sysfs hooks */ -+ data->class_dev = hwmon_device_register(&client->dev); -+ if (IS_ERR(data->class_dev)) { -+ err = PTR_ERR(data->class_dev); -+ goto exit_detach; -+ } -+ -+ device_create_file(&client->dev, &dev_attr_temp1_max); -+ device_create_file(&client->dev, &dev_attr_temp1_max_hyst); -+ device_create_file(&client->dev, &dev_attr_temp1_input); -+ device_create_file(&client->dev, &dev_attr_in1); -+ device_create_file(&client->dev, &dev_attr_in2); -+ device_create_file(&client->dev, &dev_attr_in3); -+ device_create_file(&client->dev, &dev_attr_in4); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+exit_free: -+ kfree(data); -+exit: -+ return err; -+} -+ -+static int ad741x_detach_client(struct i2c_client *client) -+{ -+ struct ad741x_data *data = i2c_get_clientdata(client); -+ hwmon_device_unregister(data->class_dev); -+ i2c_detach_client(client); -+ kfree(data); -+ return 0; -+} -+ -+static int __init ad741x_init(void) -+{ -+ return i2c_add_driver(&ad741x_driver); -+} -+ -+static void __exit ad741x_exit(void) -+{ -+ i2c_del_driver(&ad741x_driver); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); -+MODULE_DESCRIPTION("AD741X driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ad741x_init); -+module_exit(ad741x_exit); ---- linux-ixp4xx.orig/drivers/hwmon/Kconfig 2006-02-19 17:45:45.000000000 +0100 -+++ linux-ixp4xx/drivers/hwmon/Kconfig 2006-02-19 17:47:07.000000000 +0100 -@@ -433,6 +433,16 @@ config SENSORS_W83627EHF - This driver can also be built as a module. If so, the module - will be called w83627ehf. - -+config SENSORS_AD741X -+ tristate "Analog Devices AD7417/18" -+ depends on HWMON && I2C && EXPERIMENTAL -+ help -+ If you say yes here you get support for the Analog Devices AD7417 -+ and AD7418 chips. -+ -+ This driver can also be built as a module. If so, the module -+ will be called ad741x. -+ - config SENSORS_HDAPS - tristate "IBM Hard Drive Active Protection System (hdaps)" - depends on HWMON && INPUT && X86 diff --git a/packages/linux/ixp4xx-kernel/2.6.16/65-loft-config.patch b/packages/linux/ixp4xx-kernel/2.6.16/65-loft-config.patch deleted file mode 100644 index eddaad8166..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/65-loft-config.patch +++ /dev/null @@ -1,90 +0,0 @@ -support for the Giant Shoulder Inc Loft board - a very minor -variation on a standard Avila board - - arch/arm/mach-ixp4xx/Kconfig | 8 +++++++- - arch/arm/mach-ixp4xx/ixdp425-pci.c | 6 ++++-- - arch/arm/mach-ixp4xx/ixdp425-setup.c | 19 +++++++++++++++++++ - include/asm-arm/arch-ixp4xx/ixdp425.h | 1 + - 4 files changed, 31 insertions(+), 3 deletions(-) - ---- linux-nslu2.orig/arch/arm/mach-ixp4xx/Kconfig 2006-02-06 20:37:01.000000000 +0100 -+++ linux-nslu2/arch/arm/mach-ixp4xx/Kconfig 2006-02-06 22:34:20.000000000 +0100 -@@ -25,6 +25,12 @@ config ARCH_AVILA - Avila Network Platform. For more information on this platform, - see <file:Documentation/arm/IXP4xx>. - -+config MACH_LOFT -+ bool "Loft" -+ help -+ Say 'Y' here if you want your kernel to support the Giant -+ Shoulder Inc Loft board. -+ - config ARCH_ADI_COYOTE - bool "Coyote" - help -@@ -84,7 +90,7 @@ config MACH_NAS100D - # - config ARCH_IXDP4XX - bool -- depends on ARCH_IXDP425 || ARCH_AVILA || MACH_IXDP465 -+ depends on ARCH_IXDP425 || ARCH_AVILA || MACH_IXDP465 || MACH_LOFT - default y - - # ---- linux-nslu2.orig/arch/arm/mach-ixp4xx/ixdp425-pci.c 2006-02-06 20:37:01.000000000 +0100 -+++ linux-nslu2/arch/arm/mach-ixp4xx/ixdp425-pci.c 2006-02-06 22:34:20.000000000 +0100 -@@ -46,7 +46,8 @@ static int __init ixdp425_map_irq(struct - - int irq = -1; - -- if (slot >= 1 && slot <= IXDP425_PCI_MAX_DEV && -+ if (slot >= 1 && -+ slot <= (machine_is_loft() ? LOFT_PCI_MAX_DEV : IXDP425_PCI_MAX_DEV) && - pin >= 1 && pin <= IXDP425_PCI_IRQ_LINES) { - irq = pci_irq_table[(slot + pin - 2) % 4]; - } -@@ -66,7 +67,8 @@ struct hw_pci ixdp425_pci __initdata = { - int __init ixdp425_pci_init(void) - { - if (machine_is_ixdp425() || machine_is_ixcdp1100() || -- machine_is_avila() || machine_is_ixdp465()) -+ machine_is_avila() || machine_is_ixdp465() || -+ machine_is_loft()) - pci_common_init(&ixdp425_pci); - return 0; - } ---- linux-nslu2.orig/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-02-06 20:37:01.000000000 +0100 -+++ linux-nslu2/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-02-06 22:34:20.000000000 +0100 -@@ -176,3 +176,22 @@ MACHINE_START(AVILA, "Gateworks Avila Ne - MACHINE_END - #endif - -+/* -+ * Loft is functionally equivalent to Avila except that it has a -+ * different number for the maximum PCI devices. The MACHINE -+ * structure below is identical to Avila except for the comment. -+ */ -+#ifdef CONFIG_MACH_LOFT -+MACHINE_START(LOFT, "Giant Shoulder Inc Loft board") -+ /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */ -+ .phys_ram = PHYS_OFFSET, -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = ixdp425_init, -+MACHINE_END -+#endif -+ ---- linux-nslu2.orig/include/asm-arm/arch-ixp4xx/ixdp425.h 2006-02-06 20:37:38.000000000 +0100 -+++ linux-nslu2/include/asm-arm/arch-ixp4xx/ixdp425.h 2006-02-06 22:34:20.000000000 +0100 -@@ -23,6 +23,7 @@ - * IXDP425 PCI IRQs - */ - #define IXDP425_PCI_MAX_DEV 4 -+#define LOFT_PCI_MAX_DEV 6 - #define IXDP425_PCI_IRQ_LINES 4 - - diff --git a/packages/linux/ixp4xx-kernel/2.6.16/75-dsmg600.patch b/packages/linux/ixp4xx-kernel/2.6.16/75-dsmg600.patch deleted file mode 100644 index 3603bd3ca8..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/75-dsmg600.patch +++ /dev/null @@ -1,353 +0,0 @@ ---- - arch/arm/mach-ixp4xx/Kconfig | 8 + - arch/arm/mach-ixp4xx/Makefile | 1 - arch/arm/mach-ixp4xx/dsmg600-pci.c | 74 +++++++++++++++++ - arch/arm/mach-ixp4xx/dsmg600-setup.c | 139 +++++++++++++++++++++++++++++++++ - arch/arm/tools/mach-types | 1 - include/asm-arm/arch-ixp4xx/dsmg600.h | 62 ++++++++++++++ - include/asm-arm/arch-ixp4xx/hardware.h | 1 - include/asm-arm/arch-ixp4xx/irqs.h | 10 ++ - 8 files changed, 296 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/Kconfig 2006-03-18 18:10:31.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/Kconfig 2006-03-18 18:10:34.000000000 +0100 -@@ -83,6 +83,14 @@ config MACH_NAS100D - NAS 100d device. For more information on this platform, - see http://www.nslu2-linux.org/wiki/NAS100d/HomePage - -+config MACH_DSMG600 -+ bool -+ prompt "D-Link DSM-G600" -+ help -+ Say 'Y' here if you want your kernel to support D-Link's -+ DSM-G600 device. For more information on this platform, -+ see http://www.nslu2-linux.org/ -+ - # - # Avila and IXDP share the same source for now. Will change in future - # ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/dsmg600-pci.c 2006-03-18 18:10:34.000000000 +0100 -@@ -0,0 +1,74 @@ -+/* -+ * DSM-G600 board-level PCI initialization -+ * -+ * Copyright (c) 2006 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on ixdp425-pci.c: -+ * Copyright (C) 2002 Intel Corporation. -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Maintainer: http://www.nslu2-linux.org/ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+ -+#include <asm/mach/pci.h> -+#include <asm/mach-types.h> -+ -+void __init dsmg600_pci_preinit(void) -+{ -+ set_irq_type(IRQ_DSMG600_PCI_INTA, IRQT_LOW); -+ set_irq_type(IRQ_DSMG600_PCI_INTB, IRQT_LOW); -+ set_irq_type(IRQ_DSMG600_PCI_INTC, IRQT_LOW); -+ set_irq_type(IRQ_DSMG600_PCI_INTD, IRQT_LOW); -+ set_irq_type(IRQ_DSMG600_PCI_INTE, IRQT_LOW); -+ set_irq_type(IRQ_DSMG600_PCI_INTF, IRQT_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init dsmg600_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ static int pci_irq_table[DSMG600_PCI_MAX_DEV][DSMG600_PCI_IRQ_LINES] = -+ { -+ { IRQ_DSMG600_PCI_INTE, -1, -1 }, -+ { IRQ_DSMG600_PCI_INTA, -1, -1 }, -+ { IRQ_DSMG600_PCI_INTB, IRQ_DSMG600_PCI_INTC, IRQ_DSMG600_PCI_INTD }, -+ { IRQ_DSMG600_PCI_INTF, -1, -1 }, -+ }; -+ -+ int irq = -1; -+ -+ if (slot >= 1 && slot <= DSMG600_PCI_MAX_DEV && -+ pin >= 1 && pin <= DSMG600_PCI_IRQ_LINES) -+ irq = pci_irq_table[slot-1][pin-1]; -+ -+ return irq; -+} -+ -+struct hw_pci __initdata dsmg600_pci = { -+ .nr_controllers = 1, -+ .preinit = dsmg600_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = dsmg600_map_irq, -+}; -+ -+int __init dsmg600_pci_init(void) -+{ -+ if (machine_is_dsmg600()) -+ pci_common_init(&dsmg600_pci); -+ -+ return 0; -+} -+ -+subsys_initcall(dsmg600_pci_init); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/dsmg600-setup.c 2006-03-18 18:10:34.000000000 +0100 -@@ -0,0 +1,139 @@ -+/* -+ * DSM-G600 board-setup -+ * -+ * Copyright (c) 2006 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based ixdp425-setup.c: -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * Maintainers: http://www.nslu2-linux.org/ -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/serial.h> -+#include <linux/serial_8250.h> -+ -+#include <asm/mach-types.h> -+#include <asm/mach/arch.h> -+#include <asm/mach/flash.h> -+ -+static struct flash_platform_data dsmg600_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource dsmg600_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device dsmg600_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev.platform_data = &dsmg600_flash_data, -+ .num_resources = 1, -+ .resource = &dsmg600_flash_resource, -+}; -+ -+static struct ixp4xx_i2c_pins dsmg600_i2c_gpio_pins = { -+ .sda_pin = DSMG600_SDA_PIN, -+ .scl_pin = DSMG600_SCL_PIN, -+}; -+ -+static struct platform_device dsmg600_i2c_controller = { -+ .name = "IXP4XX-I2C", -+ .id = 0, -+ .dev.platform_data = &dsmg600_i2c_gpio_pins, -+ .num_resources = 0, -+}; -+ -+static struct resource dsmg600_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct plat_serial8250_port dsmg600_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { } -+}; -+ -+static struct platform_device dsmg600_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = dsmg600_uart_data, -+ .num_resources = 2, -+ .resource = dsmg600_uart_resources, -+}; -+ -+static struct platform_device *dsmg600_devices[] __initdata = { -+ &dsmg600_i2c_controller, -+ &dsmg600_flash, -+ &dsmg600_uart, -+}; -+ -+static void dsmg600_power_off(void) -+{ -+ /* enable the pwr cntl gpio */ -+// gpio_line_config(DSMG600_GPIO_PWROFF, IXP4XX_GPIO_OUT); -+ -+ /* poweroff */ -+// gpio_line_set(DSMG600_GPIO_PWROFF, IXP4XX_GPIO_HIGH); -+} -+ -+static void __init dsmg600_init(void) -+{ -+ /* The DSM-G600 has a 33MHz crystal on board - 1.01% different -+ * from the typical value. -+ */ -+ -+#ifndef FREQ -+ ixp4xx_set_board_tick_rate(66000000); -+#endif -+ -+ ixp4xx_sys_init(); -+ -+ dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ dsmg600_flash_resource.end = -+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; -+ -+ pm_power_off = dsmg600_power_off; -+ -+ platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices)); -+} -+ -+MACHINE_START(DSMG600, "D-Link DSM-G600") -+ /* Maintainer: www.nslu2-linux.org */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, -+ .boot_params = 0x00000100, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .init_machine = dsmg600_init, -+MACHINE_END ---- linux-ixp4xx.orig/arch/arm/tools/mach-types 2006-03-18 18:10:31.000000000 +0100 -+++ linux-ixp4xx/arch/arm/tools/mach-types 2006-03-18 18:10:34.000000000 +0100 -@@ -969,3 +969,4 @@ mxc300_30ads MACH_MXC30030ADS MXC30030A - fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956 - dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957 - gesbc9312 MACH_GESBC9312 GESBC9312 958 -+dsmg600 MACH_DSMG600 DSMG600 964 ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/dsmg600.h 2006-03-18 18:10:34.000000000 +0100 -@@ -0,0 +1,62 @@ -+/* -+ * DSM-G600 platform specific definitions -+ * -+ * Copyright (c) 2006 Tower Technologies -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * -+ * based on ixdp425.h: -+ * Copyright 2004 (c) MontaVista, Software, Inc. -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#ifndef __ASM_ARCH_HARDWARE_H__ -+#error "Do not include this directly, instead #include <asm/hardware.h>" -+#endif -+ -+#define DSMG600_SDA_PIN 5 -+#define DSMG600_SCL_PIN 4 -+ -+/* -+ * DSMG600 PCI IRQs -+ */ -+#define DSMG600_PCI_MAX_DEV 4 -+#define DSMG600_PCI_IRQ_LINES 3 -+ -+ -+/* PCI controller GPIO to IRQ pin mappings */ -+#define DSMG600_PCI_INTA_PIN 11 -+#define DSMG600_PCI_INTB_PIN 10 -+#define DSMG600_PCI_INTC_PIN 9 -+#define DSMG600_PCI_INTD_PIN 8 -+#define DSMG600_PCI_INTE_PIN 7 -+#define DSMG600_PCI_INTF_PIN 6 -+ -+/* GPIO */ -+ -+#define DSMG600_GPIO0 0 -+#define DSMG600_GPIO1 1 -+#define DSMG600_GPIO2 2 -+#define DSMG600_GPIO3 3 -+#define DSMG600_GPIO4 4 -+#define DSMG600_GPIO5 5 -+#define DSMG600_GPIO6 6 -+#define DSMG600_GPIO7 7 -+#define DSMG600_GPIO8 8 -+#define DSMG600_GPIO9 9 -+#define DSMG600_GPIO10 10 -+#define DSMG600_GPIO11 11 -+#define DSMG600_GPIO12 12 -+#define DSMG600_GPIO13 13 -+#define DSMG600_GPIO14 14 -+#define DSMG600_GPIO15 15 -+ -+#define DSMG600_GPIO_PWRBTN DSMG600_GPIO15 /* power */ -+#define DSMG600_GPIO_RSTBTN DSMG600_GPIO3 /* reset */ -+ -+#define DSMG600_IRQ_PWRBTN IRQ_IXP4XX_GPIO15 -+#define DSMG600_IRQ_RSTBTN IRQ_IXP4XX_GPIO3 -+ -+#define DSMG600_GPIO_PWROFF DSMG600_GPIO2 /* power off */ ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/Makefile 2006-03-18 18:10:31.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/Makefile 2006-03-18 18:10:34.000000000 +0100 -@@ -10,4 +10,5 @@ obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote- - obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o - obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o - obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o -+obj-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o dsmg600-setup.o - ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/hardware.h 2006-03-18 18:10:31.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/hardware.h 2006-03-18 18:10:34.000000000 +0100 -@@ -46,5 +46,6 @@ extern unsigned int processor_id; - #include "prpmc1100.h" - #include "nslu2.h" - #include "nas100d.h" -+#include "dsmg600.h" - - #endif /* _ASM_ARCH_HARDWARE_H */ ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/irqs.h 2006-03-18 18:10:31.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/irqs.h 2006-03-18 18:10:34.000000000 +0100 -@@ -109,4 +109,14 @@ - #define IRQ_NAS100D_PCI_INTD IRQ_IXP4XX_GPIO8 - #define IRQ_NAS100D_PCI_INTE IRQ_IXP4XX_GPIO7 - -+/* -+ * D-Link DSM-G600 board IRQs -+ */ -+#define IRQ_DSMG600_PCI_INTA IRQ_IXP4XX_GPIO11 -+#define IRQ_DSMG600_PCI_INTB IRQ_IXP4XX_GPIO10 -+#define IRQ_DSMG600_PCI_INTC IRQ_IXP4XX_GPIO9 -+#define IRQ_DSMG600_PCI_INTD IRQ_IXP4XX_GPIO8 -+#define IRQ_DSMG600_PCI_INTE IRQ_IXP4XX_GPIO7 -+#define IRQ_DSMG600_PCI_INTF IRQ_IXP4XX_GPIO6 -+ - #endif diff --git a/packages/linux/ixp4xx-kernel/2.6.16/83-nas100d-memory-fixup.patch b/packages/linux/ixp4xx-kernel/2.6.16/83-nas100d-memory-fixup.patch deleted file mode 100644 index 3d5e20c6cf..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/83-nas100d-memory-fixup.patch +++ /dev/null @@ -1,66 +0,0 @@ -Include a fixup machine start function in nas100d-setup.c to handle -the command line and memory setup parameters which are not specifiable -in the boot loader. - -TODO: We must check what is actually passed by the stock -RedBoot on the nas100d. - -Signed-off-by: John Bowler <jbowler@acm.org> - - arch/arm/mach-ixp4xx/nas100d-setup.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-09 02:13:15.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-09 02:13:54.000000000 +0100 -@@ -19,6 +19,7 @@ - #include <asm/mach-types.h> - #include <asm/mach/arch.h> - #include <asm/mach/flash.h> -+#include <asm/setup.h> - - static struct flash_platform_data nas100d_flash_data = { - .map_name = "cfi_probe", -@@ -125,11 +126,43 @@ static void __init nas100d_init(void) - platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices)); - } - -+/* -+ * NAS100D bootstrap may pass in parameters, but we zap the mem -+ * settings to be safe (the box always has 64MByte at 0). The -+ * passed in command line can override this default, we prepend -+ * to the config'ed default. -+ * -+ * NOTE: the startup sequence is: -+ * 1) Call the machine fixup -+ * 2) Parse the ATAG list, the ATAG_CMDLINE is copied in -+ * to default_command_line which is the value of *from -+ * 3) Parse the command line in *from (*not* -+ * default_command_line unless they are the same!) -+ * -+ * Setting mi->nr_banks causes (2) to 'squash' (set to ATAG_NONE) -+ * any ATAG_MEM tags, but mem= command line options cause nr_banks -+ * to be reset to 0 (on the first mem=) -+ */ -+ -+static void __init nas100d_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+{ -+ /* The NAS100D has one bank of 64MByte memory. -+ * NOTE: setting nr_banks != 0 causes kernel/setup.c to remove -+ * the mem tags from the tag list. We need do nothing here! -+ */ -+ mi->nr_banks = 1; -+ mi->bank[0].start = 0; -+ mi->bank[0].size = (64*1024*1024); -+ mi->bank[0].node = PHYS_TO_NID(0); -+} -+ - MACHINE_START(NAS100D, "Iomega NAS 100d") - /* Maintainer: www.nslu2-linux.org */ - .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, - .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, - .boot_params = 0x00000100, -+ .fixup = nas100d_fixup, - .map_io = ixp4xx_map_io, - .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, diff --git a/packages/linux/ixp4xx-kernel/2.6.16/84-nas100d-cmdline.patch b/packages/linux/ixp4xx-kernel/2.6.16/84-nas100d-cmdline.patch deleted file mode 100644 index 2f02f5622d..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/84-nas100d-cmdline.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- - arch/arm/mach-ixp4xx/nas100d-setup.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-09 02:14:52.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-09 02:16:43.000000000 +0100 -@@ -144,6 +144,12 @@ static void __init nas100d_init(void) - * to be reset to 0 (on the first mem=) - */ - -+static char nas100d_command_line[] __initdata = -+ "root=/dev/mtdblock2 rootfstype=jffs2 init=/linuxrc " -+ "rtc-pcf8563.probe=0,0x51 " -+ CONFIG_CMDLINE; -+ -+ - static void __init nas100d_fixup(struct machine_desc *desc, - struct tag *tags, char **cmdline, struct meminfo *mi) - { -@@ -155,6 +161,11 @@ static void __init nas100d_fixup(struct - mi->bank[0].start = 0; - mi->bank[0].size = (64*1024*1024); - mi->bank[0].node = PHYS_TO_NID(0); -+ -+ /* A command line in the ATAG list will override this one, -+ * as is intended. -+ */ -+ strlcpy(*cmdline, nas100d_command_line, COMMAND_LINE_SIZE); - } - - MACHINE_START(NAS100D, "Iomega NAS 100d") diff --git a/packages/linux/ixp4xx-kernel/2.6.16/85-timer.patch b/packages/linux/ixp4xx-kernel/2.6.16/85-timer.patch deleted file mode 100644 index 83951c2574..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/85-timer.patch +++ /dev/null @@ -1,280 +0,0 @@ - arch/arm/mach-ixp4xx/common.c | 165 +++++++++++++++++++++++++++++++++--- - arch/arm/mach-ixp4xx/nslu2-setup.c | 5 + - include/asm-arm/arch-ixp4xx/nslu2.h | 5 - - include/asm-arm/arch-ixp4xx/timex.h | 23 +++-- - 4 files changed, 176 insertions(+), 22 deletions(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/common.c 2006-02-23 18:27:49.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/common.c 2006-02-23 18:30:49.000000000 +0100 -@@ -247,36 +247,165 @@ void __init ixp4xx_init_irq(void) - * IXP4xx timer tick - * We use OS timer1 on the CPU for the timer tick and the timestamp - * counter as a source of real clock ticks to account for missed jiffies. -+ * -+ * 'CLOCK_TICK_RATE' is the nominal number of internal ticks per second, -+ * this is significantly greater than the actual number on any ixp4xx -+ * board. Neither this nor 'LATCH' are required by this code because -+ * the only requirement is to generate HZ timer_tick calls per second. - *************************************************************************/ -+#if TICK_NSEC * HZ != 1000000000 -+ /* This will cause the jiffies to drift unnecessarily. */ -+# error CLOCK_TICK_RATE should be a multiple of HZ for this code -+#endif -+ -+/* These are the control registers for the interrupt handler, they must -+ * only be read and written by the interrupt handler and by the init -+ * method (which sets them to 0). -+ */ -+static volatile u32 last_timer_time; -+static volatile int accumulated_error; -+ -+/* Most ixp4xx boards have 66.6666MHz crystals, so default to this, reset -+ * this from the board level code if required. The following variables -+ * must be *written* only by set_board_tick_rate -+ */ -+static u32 board_tick_rate; -+static u32 board_tick_per_1000; /* board_tick_rate/1000 */ -+static u32 timer_count; -+ -+/* The following symbol may be written to change the current tick rate, -+ * it is read by the interrupt handler and used to reload the timer. -+ * The 'real' value (the one in use) is 'board_tick_rate' above. -+ * NOTE: this can be tweaked to match the actual crystal on a particular -+ * machine. -+ */ -+volatile u32 ixp4xx_board_tick_rate = 66666600; -+EXPORT_SYMBOL(ixp4xx_board_tick_rate); -+ -+/* The set API may run asynchronously in the presence of interrupts, -+ * everything it does it is both atomic and complete (notice that it -+ * doesn't change any of the 'volatile' values). The mathematics in -+ * here require the following values. Changing the board tick rate -+ * implies an unknown error in the current timestamp tick count. -+ */ -+#if IXP4XX_OST_RELOAD_MASK != 3 || IXP4XX_OST_ENABLE != 1 -+# error unexpected value for timer reload mask -+#endif -+static void set_board_tick_rate(u32 rate) { -+ u32 reload; -+ -+ /* Store the two effectively informational rate values, the -+ * error calculation is (rate - count*HZ) (above), and rate -+ * is changed first, this can cause a temporary error which -+ * will be corrected on the next interrupt. -+ */ -+ board_tick_rate = rate; -+ board_tick_per_1000 = (rate+500)/1000; -+ -+ /* Calculate the correct value to load into the timer countdown -+ * register, the low two bits must be b01 (to enable the timer). -+ * Select the top bits to be as close to the desired value as -+ * possible. -+ * -+ * First find the best value, regardless of the low two bits - -+ * this is the value used in the interrupt calculation even though -+ * it cannot necessarily be set into the register. -+ */ -+ timer_count = (rate + (HZ/2))/HZ; -+ -+ /* Now the timer_ticks are being generated at this rate, calculate -+ * an appropriate value for the register. This stores a 30 bit -+ * value which gives a period of 4*x+1, we want: -+ * -+ * 4*x+1 = board_tick_rate/HZ -+ * -+ * This needs to be rounded to the closest 4*HZ value: -+ * -+ * x = ((board_tick_rate-HZ) + (4*HZ)/2) / 4*HZ -+ * x = (board_tick_rate+HZ) / (4*HZ); -+ */ -+ reload = (board_tick_rate + HZ) / HZ; -+ reload = (reload & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; -+ *IXP4XX_OSRT1 = reload; - --static unsigned volatile last_jiffy_time; -+ /* If the clock is drifing, look in syslog: */ -+ printk(KERN_INFO "IXP4xx: FREQ=%d COUNT=%d\n", rate, reload); -+} - --#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) -+/* This returns the time in timer ticks since the 'last_timer_time' -+ * recorded above. Use this to avoid arithmetic errors because of -+ * the overflow when the timer wraps. -+ */ -+static inline u32 ixp4xx_timer_delta(void) -+{ -+ return *IXP4XX_OSTS - last_timer_time; -+} - - /* IRQs are disabled before entering here from do_gettimeofday() */ - static unsigned long ixp4xx_gettimeoffset(void) - { -- u32 elapsed; -- -- elapsed = *IXP4XX_OSTS - last_jiffy_time; -+ /* Return the offset of the current time from the last time -+ * timer tick in microseconds. This is only used for the -+ * gettimeofday call. -+ * -+ * The result of this API is at most about 20000 (for a 50Hz -+ * HZ - 20000 uS/tick), the input delta is at most about -+ * 1.3M - 21 bits. -+ */ -+ u32 delta = ixp4xx_timer_delta(); /* About 21 bits max */ -+ /* return delta * 1000000 / board_tick_rate; */ -+ return (delta * 1000 + board_tick_per_1000/2) / board_tick_per_1000; -+} - -- return elapsed / CLOCK_TICKS_PER_USEC; -+/* This is the correct adjustment to the counter to compensate for an -+ * error iff timer_count-1 <= exact_count <= timer_count+1 -+ */ -+static inline int adjustment(int error) { -+ if (error >= HZ) -+ return 1; -+ else if (error <= -HZ) -+ return -1; -+ return 0; - } - - static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) - { -+ u32 rate; -+ u32 count; -+ int error; -+ - write_seqlock(&xtime_lock); - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - -+ /* If the board tick rate has been changed update the cached -+ * value. -+ */ -+ if (ixp4xx_board_tick_rate != board_tick_rate) { -+ set_board_tick_rate(ixp4xx_board_tick_rate); -+ accumulated_error = 0; -+ } -+ - /* - * Catch up with the real idea of time -+ * -+ * board_tick_rate: actual ixp4xx ticks/second, read-only -+ * accumulated_error: aggregate error/tick * HZ, read/write -+ * timer_count: best ixp4xx ticks per timer_tick, read-only - */ -- while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { -+ rate = board_tick_rate; -+ error = accumulated_error; -+ count = timer_count; -+ do { -+ u32 adjusted_count = count + adjustment(error); -+ if (ixp4xx_timer_delta() < adjusted_count) -+ break; - timer_tick(regs); -- last_jiffy_time += LATCH; -- } -+ last_timer_time += adjusted_count; -+ error += rate - adjusted_count*HZ; -+ } while (1); -+ accumulated_error = error; - - write_sequnlock(&xtime_lock); - -@@ -289,17 +418,30 @@ static struct irqaction ixp4xx_timer_irq - .handler = ixp4xx_timer_interrupt, - }; - -+u32 ixp4xx_get_board_tick_rate(void) { -+ return board_tick_rate; -+} -+ -+EXPORT_SYMBOL(ixp4xx_get_board_tick_rate); -+ -+void ixp4xx_set_board_tick_rate(u32 rate) { -+ ixp4xx_board_tick_rate = rate; -+} -+ -+EXPORT_SYMBOL(ixp4xx_set_board_tick_rate); -+ - static void __init ixp4xx_timer_init(void) - { - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - /* Setup the Timer counter value */ -- *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; -+ set_board_tick_rate(ixp4xx_board_tick_rate); - - /* Reset time-stamp counter */ - *IXP4XX_OSTS = 0; -- last_jiffy_time = 0; -+ last_timer_time = 0; -+ accumulated_error = 0; - - /* Connect the interrupt handler and enable the interrupt */ - setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); -@@ -362,4 +504,3 @@ void __init ixp4xx_sys_init(void) - printk("IXP4xx: Using %luMiB expansion bus window size\n", - ixp4xx_exp_bus_size >> 20); - } -- ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-23 18:27:49.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-23 18:30:49.000000000 +0100 -@@ -119,6 +119,11 @@ static void nslu2_power_off(void) - - static void __init nslu2_init(void) - { -+ /* The NSLU2 has a 33MHz crystal on board - 1.01% different -+ * from the typical value. -+ */ -+ ixp4xx_set_board_tick_rate(66000000); -+ - ixp4xx_sys_init(); - - nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/nslu2.h 2006-02-23 18:27:12.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/nslu2.h 2006-02-23 18:30:49.000000000 +0100 -@@ -35,11 +35,6 @@ - #define NSLU2_PCI_INTD_PIN 8 - - --/* NSLU2 Timer */ --#define NSLU2_FREQ 66000000 --#define NSLU2_CLOCK_TICK_RATE (((NSLU2_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) --#define NSLU2_CLOCK_TICKS_PER_USEC ((NSLU2_CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) -- - /* GPIO */ - - #define NSLU2_GPIO0 0 ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/timex.h 2006-02-23 18:27:12.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/timex.h 2006-02-23 18:30:49.000000000 +0100 -@@ -6,10 +6,23 @@ - #include <asm/hardware.h> - - /* -- * We use IXP425 General purpose timer for our timer needs, it runs at -- * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the -- * timer register ignores the bottom 2 bits of the LATCH value. -+ * In linux/timex.h 'LATCH' is defined as CLOCK_TICK_RATE/HZ and -+ * is the number of internal counts per timer interrupt. Thus -+ * CLOCK_TICK_RATE is LATCH*HZ. -+ * -+ * The actual values of these numbers do not matter, because they -+ * are only used to calculate ACTHZ (rate/latch as a 24.8 fixed -+ * point number), so the value here gives a LATCH of 1 and pretty -+ * much guarantees to flush out any off-by-one errors. -+ * -+ * ACTHZ is equal to HZ, because CLOCK_TICK_RATE is a multiple of -+ * HZ, this is checked in the ixp4xx/common.c code. - */ --#define FREQ 66666666 --#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) -+#define CLOCK_TICK_RATE HZ - -+/* The following allow the exact board tick rate to be set and -+ * discovered. The value should be exactly twice the frequency -+ * (in Hz) of the onboard crystal. -+ */ -+extern u32 ixp4xx_get_board_tick_rate(void); -+extern void ixp4xx_set_board_tick_rate(u32 new_rate); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/91-maclist.patch b/packages/linux/ixp4xx-kernel/2.6.16/91-maclist.patch deleted file mode 100644 index 34579183d0..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/91-maclist.patch +++ /dev/null @@ -1,573 +0,0 @@ -Ethernet MAC repository. - -Some ethernet controllers have no built-in way of obtaining an -appropriate Ethernet MAC address. Such controllers have to be -initialised in a board-specific way, depending on how the allocated -MAC is stored. The MAC repository provides a set of APIs and a -proc entry (/proc/net/maclist) to store MAC values from the board -so that such drivers can obtain a MAC address without board-specific -code. - -Signed-off-by: John Bowler <jbowler@acm.org> - ---- - drivers/net/Kconfig | 15 + - drivers/net/Makefile | 1 - drivers/net/maclist.c | 465 ++++++++++++++++++++++++++++++++++++++++++++++++++ - include/net/maclist.h | 49 +++++ - 4 files changed, 530 insertions(+) - ---- linux-ixp4xx.orig/drivers/net/Kconfig 2006-02-23 18:27:12.000000000 +0100 -+++ linux-ixp4xx/drivers/net/Kconfig 2006-02-23 18:30:54.000000000 +0100 -@@ -177,6 +177,21 @@ config NET_ETHERNET - kernel: saying N will just cause the configurator to skip all - the questions about Ethernet network cards. If unsure, say N. - -+config MACLIST -+ tristate "Ethernet MAC repository" -+ depends on NET_ETHERNET -+ help -+ Some ethernet controllers have no built-in way of obtaining an -+ appropriate Ethernet MAC address. Such controllers have to be -+ initialised in a board-specific way, depending on how the allocated -+ MAC is stored. The MAC repository provides a set of APIs and a -+ proc entry (/proc/net/maclist) to store MAC values from the board -+ so that such drivers can obtain a MAC address without board-specific -+ code. You do not need to enable this device - it will be selected -+ automatically by any device which requires it. It is only useful -+ to enable it manually when building a device driver independently -+ of the kernel build. -+ - config MII - tristate "Generic Media Independent Interface device support" - depends on NET_ETHERNET ---- linux-ixp4xx.orig/drivers/net/Makefile 2006-02-23 18:27:12.000000000 +0100 -+++ linux-ixp4xx/drivers/net/Makefile 2006-02-23 18:30:54.000000000 +0100 -@@ -74,6 +74,7 @@ obj-$(CONFIG_RIONET) += rionet.o - # end link order section - # - -+obj-$(CONFIG_MACLIST) += maclist.o - obj-$(CONFIG_MII) += mii.o - obj-$(CONFIG_PHYLIB) += phy/ - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/net/maclist.c 2006-02-23 18:30:54.000000000 +0100 -@@ -0,0 +1,465 @@ -+/* -+ * drivers/net/maclist.c -+ * -+ * a simple driver to remember ethernet MAC values -+ * -+ * Some Ethernet hardware implementations have no built-in -+ * storage for allocated MAC values - an example is the Intel -+ * IXP420 chip which has support for Ethernet but no defined -+ * way of storing allocated MAC values. With such hardware -+ * different board level implementations store the allocated -+ * MAC (or MACs) in different ways. Rather than put board -+ * level code into a specific Ethernet driver this driver -+ * provides a generally accessible repository for the MACs -+ * which can be written by board level code and read by the -+ * driver. -+ * -+ * The implementation also allows user level programs to -+ * access the MAC information in /proc/net/maclist. This is -+ * useful as it allows user space code to use the MAC if it -+ * is not used by a built-in driver. -+ * -+ * Copyright (C) 2005 John Bowler -+ * Author: John Bowler <jbowler@acm.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ */ -+ -+/* -+ * External interfaces: -+ * Interfaces to linux kernel (and modules) -+ * maclist_add: add a single MAC, sequenced with a single -+ * writer lock (reads may happen simultaneously -+ * because of the way the list is built) -+ * maclist_count: total number of MACs stored -+ * maclist_read: read a MAC 0..(maclist_count-1). Call this -+ * to get a specific MAC. If the argument is -+ * a new key and all the allocaed MACs have been -+ * assigned a random but valid MAC will be return -+ * (and this will be stored for later retrieval -+ * under the given key.) -+ * -+ * Sequencing: -+ * The MAC ids must be added before any driver tries to use them -+ * (this is obvious isn't it?) This can be made to happen by -+ * sequencing the initcalls correctly. The module or kernel -+ * parameters have been handled before any init call happens. -+ * The important trick here is to ensure that the platform -+ * initialises any devices with MAC ids *before* any devices -+ * which might use them. -+ * -+ * When this code is a module any other module which adds a -+ * MAC should be modprobed before modules for ethernet -+ * devices. -+ * -+ * The failure case is 'soft' - the device will get a valid, but -+ * random, MAC and the real allocated MACs will never get used. -+ * This can be seen by looking at the list of ids in sysfs (there -+ * will be extra, random, ones after the allocated ones). -+ * -+ * Recommendations: -+ * For ethernet drivers which are known to be the sole driver on -+ * the board (without a built in MAC) and where the number of -+ * devices driven is known simply use an index 0..(n-1) as a -+ * key for each of the n devices. -+ * -+ * This is the common case, it works where one driver handles -+ * multiple devices so long as the total number of devices can -+ * be determined reliably. It is sufficient merely to maintain -+ * a global count of the number of devices initialised so far, -+ * just so long as the initialisation order is consistent. -+ * -+ * When the driver is generic and the board may be populated with -+ * other devices which allocate MACs from the maclist pool and -+ * use different drivers create a random key and compile this into -+ * the code. Use this as the base for all devices from the driver -+ * (using a global device count for this driver if necessary). -+ * -+ * With the second strategy the assignment of MACs will depend on -+ * the order of initialisation of the different drivers. To avoid -+ * this provide a kernel (or module) command line parameter to -+ * specify a base index and (optional) count for each driver or -+ * pass in a (struct resource) with the start and end of the keys -+ * to pass to maclist_read. Either method allows the higher levels -+ * (boot loader or machine description) to specify which MACs in -+ * the list to assign to each device. -+ */ -+#include <linux/module.h> -+#include <linux/moduleparam.h> -+#include <linux/spinlock.h> -+#include <linux/etherdevice.h> -+#include <linux/proc_fs.h> -+#include <linux/errno.h> -+ -+#include <net/maclist.h> -+ -+#define MACLIST_NAME "maclist" -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("MAC list repository"); -+MODULE_LICENSE("GPL"); -+ -+typedef struct maclist_entry { -+ struct maclist_entry *next; /* Linked list, first first */ -+ u32 key; /* count or key for this entry */ -+ u16 flags; -+ u8 id[6]; /* 6 byte Ethernet MAC */ -+} maclist_entry_t; -+ -+/* -+ * flag definitions -+ */ -+#define MACLIST_ALLOCATED 1 -+#define MACLIST_RANDOM 2 -+ -+/* Access to this list is protected by a standard rwlock_t. */ -+static maclist_entry_t *maclist_list = 0; -+ -+static DEFINE_RWLOCK(maclist_lock); -+ -+/* -+ * External interfaces. -+ * -+ * Add a single entry, returns 0 on success else an error -+ * code. Checks for invalid addresses. -+ */ -+int maclist_add(const u8 new_id[6]) { -+ maclist_entry_t *new_entry, **tail; -+ -+ if (new_id == 0 || !is_valid_ether_addr(new_id)) { -+ printk(KERN_ERR MACLIST_NAME ": invalid ethernet address\n"); -+ return -EINVAL; -+ } -+ new_entry = kmalloc(sizeof *new_entry, GFP_KERNEL); -+ if (new_entry == 0) -+ return -ENOMEM; -+ new_entry->next = 0; -+ new_entry->key = 0; -+ new_entry->flags = 0; -+ memcpy(new_entry->id, new_id, sizeof new_entry->id); -+ -+ tail = &maclist_list; -+ -+ write_lock(&maclist_lock); -+ while (*tail != 0) -+ tail = &(*tail)->next; -+ *tail = new_entry; -+ write_unlock(&maclist_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL(maclist_add); -+ -+/* -+ * Return the current entry count. -+ */ -+static int maclist_count_unlocked(void) { -+ maclist_entry_t *tail = maclist_list; -+ int count = 0; -+ -+ while (tail != 0) { -+ tail = tail->next; -+ ++count; -+ } -+ -+ return count; -+} -+ -+int maclist_count(void) { -+ int count; -+ -+ read_lock(&maclist_lock); -+ count = maclist_count_unlocked(); -+ read_unlock(&maclist_lock); -+ -+ return count; -+} -+EXPORT_SYMBOL(maclist_count); -+ -+/* -+ * Return the ID with the given key (the key is allocated -+ * to an entry if not found). -+ */ -+void maclist_read(u8 (*id)[6], u32 key) { -+ int count, index; -+ maclist_entry_t *entry, *entry_to_allocate; -+ -+ /* Do this under a write lock to avoid the SMP race -+ * where we find the key isn't assigned, drop the lock, -+ * have another CPU assign it, then assign it on this -+ * CPU too - very bad... -+ */ -+ write_lock(&maclist_lock); -+ count = maclist_count_unlocked(); -+ index = key % count; /* index of entry to allocate */ -+ entry_to_allocate = 0; -+ -+ entry = maclist_list; -+ while (entry != 0) { -+ if ((entry->flags & MACLIST_ALLOCATED) != 0) { -+ if (entry->key == key) { -+ /* Found it, use this entry. */ -+ entry_to_allocate = entry; -+ break; -+ } -+ } else if (entry_to_allocate == 0 || count <= index) { -+ /* The algorithm is to try for entry -+ * (key % count), but if this isn't possible -+ * return the prior unallocated entry. -+ */ -+ entry_to_allocate = entry; -+ } -+ -+ ++count; -+ entry = entry->next; -+ } -+ -+ /* Use entry_to_allocate, allocating it if necessary. */ -+ if (entry_to_allocate != 0) { -+ if ((entry_to_allocate->flags & MACLIST_ALLOCATED) == 0) { -+ entry_to_allocate->key = key; -+ entry_to_allocate->flags |= MACLIST_ALLOCATED; -+ } -+ memcpy(id, entry_to_allocate->id, sizeof *id); -+ } -+ write_unlock(&maclist_lock); -+ -+ if (entry_to_allocate == 0) { -+ /* No unallocated entries. Make a new one and return it. */ -+ printk(KERN_INFO MACLIST_NAME ": adding random MAC for key 0x%x\n", key); -+ random_ether_addr(*id); -+ if (maclist_add(*id) == 0) -+ maclist_read(id, key); -+ } -+} -+EXPORT_SYMBOL(maclist_read); -+ -+/* -+ * Parameter parsing. The option string is a list of MAC -+ * addresses, comma separated. (The parsing really should -+ * be somewhere central...) -+ */ -+static int __init maclist_setup(const char *param) { -+ int bytes = 0, seen_a_digit = 0; -+ u8 id[6]; -+ -+ memset(id, 0, sizeof id); -+ -+ if (param) do { -+ int digit = -1; -+ switch (*param) { -+ case '0': digit = 0; break; -+ case '1': digit = 1; break; -+ case '2': digit = 2; break; -+ case '3': digit = 3; break; -+ case '4': digit = 4; break; -+ case '5': digit = 5; break; -+ case '6': digit = 6; break; -+ case '7': digit = 7; break; -+ case '8': digit = 8; break; -+ case '9': digit = 9; break; -+ case 'a': case 'A': digit = 10; break; -+ case 'b': case 'B': digit = 11; break; -+ case 'c': case 'C': digit = 12; break; -+ case 'd': case 'D': digit = 13; break; -+ case 'e': case 'E': digit = 14; break; -+ case 'f': case 'F': digit = 15; break; -+ case ':': -+ if (seen_a_digit) -+ bytes = (bytes+1) & ~1; -+ else -+ bytes += 2; /* i.e. ff::ff is ff:00:ff */ -+ seen_a_digit = 0; -+ break; -+ case 0: -+ if (bytes == 0) /* nothing new seen so far */ -+ return 0; -+ /*fall through*/ -+ case ',': case ';': -+ if (bytes > 0) -+ bytes = 12; /* i.e. all trailing bytes 0 */ -+ break; -+ default: -+ printk(KERN_ERR MACLIST_NAME ": invalid character <%c[%d]>\n", -+ *param, *param); -+ return -EINVAL; -+ } -+ -+ if (digit >= 0) { -+ id[bytes>>1] = (id[bytes>>1] << 4) + digit; break; -+ ++bytes; -+ seen_a_digit = 1; -+ } -+ -+ if (bytes >= 12) { -+ int rc = maclist_add(id); -+ if (unlikely(rc)) -+ return rc; -+ bytes = 0; -+ seen_a_digit = 0; -+ memset(id, 0, sizeof id); -+ if (*param == 0) -+ return 0; -+ } -+ ++param; -+ } while (1); -+ -+ return 0; -+} -+ -+#if (defined CONFIG_PROC_FS) || (defined MODULE) -+/* -+ * Character device read -+ */ -+static int maclist_getchar(off_t n) { -+ static char xdigit[16] = "0123456789abcdef"; -+ maclist_entry_t *head = maclist_list; -+ int b; -+ -+ do { -+ if (head == 0) -+ return -1; -+ if (n < 18) -+ break; -+ head = head->next; -+ n -= 18; -+ } while (1); -+ -+ if (n == 17) -+ return '\n'; -+ -+ b = n/3; -+ switch (n - b*3) { -+ case 0: return xdigit[head->id[b] >> 4]; -+ case 1: return xdigit[head->id[b] & 0xf]; -+ default: return ':'; -+ } -+} -+#endif -+ -+/* -+ * procfs support, if compiled in. -+ */ -+#ifdef CONFIG_PROC_FS -+/* -+ * The extensively undocumented proc_read_t callback is implemented here. -+ * Go look in fs/proc/generic.c: -+ * -+ * Prototype: -+ * int f(char *buffer, char **start, off_t offset, -+ * int count, int *peof, void *dat) -+ * -+ * Assume that the buffer is "count" bytes in size. -+ * -+ * 2) Set *start = an address within the buffer. -+ * Put the data of the requested offset at *start. -+ * Return the number of bytes of data placed there. -+ * If this number is greater than zero and you -+ * didn't signal eof and the reader is prepared to -+ * take more data you will be called again with the -+ * requested offset advanced by the number of bytes -+ * absorbed. -+ */ -+static int maclist_proc_read(char *buffer, char **start, off_t offset, -+ int count, int *peof, void *dat) { -+ int total; -+ -+ *start = buffer; -+ total = 0; -+ -+ while (total < count) { -+ int ch = maclist_getchar(offset++); -+ if (ch == -1) { -+ *peof = 1; -+ break; -+ } -+ *buffer++ = ch; -+ ++total; -+ } -+ -+ return total; -+} -+#endif -+ -+/* -+ * set works once, at init time (the param is set to 0444 below), -+ * get works any time. -+ */ -+static int param_set_maclist(const char *val, struct kernel_param *kp) -+{ -+ if (maclist_list == 0) -+ return maclist_setup(val); -+ -+ printk(KERN_ERR MACLIST_NAME ": call to set parameters too late\n"); -+ return -EINVAL; -+} -+ -+static int param_get_maclist(char *buffer, struct kernel_param *kp) -+{ -+#ifdef MODULE -+ off_t offset = 0; -+ -+ /* buffer is only 4k! */ -+ while (offset < 4096) { -+ int ch = maclist_getchar(offset++); -+ if (ch < 0) { -+ *buffer = 0; -+ return 0; -+ } -+ *buffer++ = ch; -+ } -+ -+ *--buffer = 0; -+ return -ENOMEM; -+#else -+ return -EINVAL; -+#endif -+} -+ -+/* -+ * module: the argument is ids=mac,mac,mac -+ * kernel command line: maclist.ids=mac,mac,mac -+ */ -+#define param_check_maclist(name, p) __param_check(name, p, maclist_entry_t*) -+module_param_named(ids, maclist_list, maclist, 0444); -+MODULE_PARM_DESC(ids, "comma separated list of MAC ids\n"); -+ -+/* -+ * Finally, the init/exit functions. -+ */ -+static void __exit maclist_exit(void) -+{ -+ maclist_entry_t *list; -+ -+ remove_proc_entry(MACLIST_NAME, proc_net); -+ -+ write_lock(&maclist_lock); -+ list = maclist_list; -+ maclist_list = 0; -+ write_unlock(&maclist_lock); -+ -+ while (list != 0) { -+ maclist_entry_t *head = list; -+ list = head->next; -+ kfree(head); -+ } -+} -+ -+static int __init maclist_init(void) -+{ -+# ifdef MODULE -+ if (ids[0]) -+ maclist_setup(ids); -+# endif -+ -+ /* Ignore failure, the module will still work. */ -+ (void)create_proc_read_entry(MACLIST_NAME, S_IRUGO, proc_net, maclist_proc_read, NULL); -+ -+ return 0; -+} -+ -+module_init(maclist_init); -+module_exit(maclist_exit); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/net/maclist.h 2006-02-23 18:30:54.000000000 +0100 -@@ -0,0 +1,49 @@ -+#ifndef _MACLIST_H -+#define _MACLIST_H 1 -+/* -+ * Interfaces to the MAC repository -+ * -+ * Copyright (C) 2005 John Bowler -+ * Author: John Bowler <jbowler@acm.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ */ -+ -+/* -+ * Add a single entry, returns 0 on success else an error -+ * code. Allocates memory, claims and releases a write -+ * lock. -+ */ -+extern int maclist_add(const u8 id_to_add[6]); -+ -+/* -+ * Return the current entry count, claims and releases a -+ * read lock. -+ */ -+extern int maclist_count(void); -+ -+/* -+ * Return the ID from the given entry. Always succeeds. -+ * Claims and releases a write lock. -+ * -+ * If any entry has not been allocated for this key one -+ * is allocated. If there are no remaining unallocated -+ * entries a new one is created. -+ * -+ * If the value of the key is less than maclist_count() -+ * the entry indexed by the key (i.e. for key 'n' the -+ * n'th entry starting at 0) will be returned if available. -+ * Otherwise the entry to be returned will be unpredictable -+ * but consistent for a given value of maclist_count(). -+ */ -+extern void maclist_read(u8 (*buffer_for_id)[6], -+ u32 key_of_entry_to_return); -+ -+/* -+ * See the implementation in drivers/net/maclist.c for -+ * more information. -+ */ -+#endif /*_MACLIST_H*/ diff --git a/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-mac.patch b/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-mac.patch deleted file mode 100644 index c3d919569b..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-mac.patch +++ /dev/null @@ -1,84 +0,0 @@ - arch/arm/mach-ixp4xx/nas100d-setup.c | 64 +++++++++++++++++++++++++++++++++++ - 1 file changed, 64 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-27 03:03:47.000000000 +0200 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-27 03:37:23.000000000 +0200 -@@ -15,6 +15,9 @@ - #include <linux/kernel.h> - #include <linux/serial.h> - #include <linux/serial_8250.h> -+#include <linux/mtd/mtd.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -110,8 +113,68 @@ static void nas100d_power_off(void) - gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH); - } - -+/* -+ * When the RedBoot config partition is added the MAC address is read from -+ * it. -+ */ -+static struct sockaddr mac; -+ -+static void nas100d_flash_add(struct mtd_info *mtd) { -+ if (strcmp(mtd->name, "RedBoot config") == 0) { -+ size_t retlen; -+ int err; -+ /* the mac addr is at a known offset */ -+ err = mtd->read(mtd, 0x0FD8, 6, &retlen, (u8 *) &mac.sa_data); -+ if (err != 0 || retlen != 6) -+ printk(KERN_ERR "nas100d: mac addr read failed\n"); -+ } -+} -+ -+/* -+ * Nothing to do on remove at present. -+ */ -+static void nas100d_flash_remove(struct mtd_info *mtd) { -+} -+ -+static struct mtd_notifier nas100d_flash_notifier = { -+ .add = nas100d_flash_add, -+ .remove = nas100d_flash_remove, -+}; -+ -+static int nas100d_netdev_event(struct notifier_block *this, -+ unsigned long event, void *ptr) -+{ -+ struct net_device *dev = ptr; -+ -+ /* identify the ixp4xx eth, port 1 */ -+ if (dev->dev_addr[1] != 0x02 || dev->dev_addr[2] != 0xB3 -+ || dev->dev_addr[5] != 0x01) -+ return NOTIFY_DONE; -+ -+ if (event == NETDEV_REGISTER && is_valid_ether_addr(mac.sa_data)) { -+ mac.sa_family = dev->type; -+ dev_set_mac_address(dev, &mac); -+ printk(KERN_INFO -+ "ixp400_eth: MAC address now set to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x for port 0\n", -+ mac.sa_data[0], mac.sa_data[1], mac.sa_data[2], -+ mac.sa_data[3], mac.sa_data[4], mac.sa_data[5]); -+ } -+ -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block nas100d_netdev_notifier = { -+ .notifier_call = nas100d_netdev_event, -+}; -+ - static void __init nas100d_init(void) - { -+ /* The flash has an ethernet MAC embedded in it which we need, -+ * that is all this notifier does. -+ */ -+ register_mtd_user(&nas100d_flash_notifier); -+ register_netdevice_notifier(&nas100d_netdev_notifier); -+ - ixp4xx_sys_init(); - - /* gpio 14 and 15 are _not_ clocks */ diff --git a/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-maclist.patch b/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-maclist.patch deleted file mode 100644 index c10a77354b..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/92-nas100d-maclist.patch +++ /dev/null @@ -1,77 +0,0 @@ - arch/arm/mach-ixp4xx/Kconfig | 1 - arch/arm/mach-ixp4xx/nas100d-setup.c | 39 +++++++++++++++++++++++++++++++++++ - 2 files changed, 40 insertions(+) - ---- linux-nslu2.orig/arch/arm/mach-ixp4xx/Kconfig 2006-02-06 22:34:20.000000000 +0100 -+++ linux-nslu2/arch/arm/mach-ixp4xx/Kconfig 2006-02-06 22:35:26.000000000 +0100 -@@ -80,6 +80,7 @@ config ARCH_PRPMC1100 - config MACH_NAS100D - bool - prompt "NAS100D" -+ select MACLIST - help - Say 'Y' here if you want your kernel to support Iomega's - NAS 100d device. For more information on this platform, ---- linux-nslu2.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-02-06 20:37:01.000000000 +0100 -+++ linux-nslu2/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-02-06 22:35:26.000000000 +0100 -@@ -15,12 +15,15 @@ - #include <linux/kernel.h> - #include <linux/serial.h> - #include <linux/serial_8250.h> -+#include <linux/mtd/mtd.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> - #include <asm/mach/flash.h> - #include <asm/setup.h> - -+#include <net/maclist.h> -+ - static struct flash_platform_data nas100d_flash_data = { - .map_name = "cfi_probe", - .width = 2, -@@ -109,8 +112,44 @@ static void nas100d_power_off(void) - gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH); - } - -+/* -+ * When the RedBoot config partition is added the MAC address is read from -+ * it. -+ */ -+static void nas100d_flash_add(struct mtd_info *mtd) { -+ if (strcmp(mtd->name, "RedBoot config") == 0) { -+ size_t retlen; -+ u_char mac[6]; -+ -+ /* The MAC is at a known offset... */ -+ if (mtd->read(mtd, 0x0FD8, 6, &retlen, mac) == 0 && retlen == 6) { -+ printk(KERN_INFO "NAS100D MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", -+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); -+ maclist_add(mac); -+ } else { -+ printk(KERN_ERR "NAS100D MAC: read failed\n"); -+ } -+ } -+} -+ -+/* -+ * Nothing to do on remove at present. -+ */ -+static void nas100d_flash_remove(struct mtd_info *mtd) { -+} -+ -+static struct mtd_notifier nas100d_flash_notifier = { -+ .add = nas100d_flash_add, -+ .remove = nas100d_flash_remove, -+}; -+ - static void __init nas100d_init(void) - { -+ /* The flash has an ethernet MAC embedded in it which we need, -+ * that is all this notifier does. -+ */ -+ register_mtd_user(&nas100d_flash_notifier); -+ - ixp4xx_sys_init(); - - nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-mac.patch b/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-mac.patch deleted file mode 100644 index e96c5f9e75..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-mac.patch +++ /dev/null @@ -1,87 +0,0 @@ - arch/arm/mach-ixp4xx/nslu2-setup.c | 62 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 62 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-03-27 14:42:07.000000000 +0200 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-03-27 14:45:45.000000000 +0200 -@@ -16,6 +16,9 @@ - #include <linux/kernel.h> - #include <linux/serial.h> - #include <linux/serial_8250.h> -+#include <linux/mtd/mtd.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -117,6 +120,58 @@ static void nslu2_power_off(void) - gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH); - } - -+/* -+ * When the RedBoot config partition is added the MAC address is read from -+ * it. -+ */ -+static struct sockaddr mac; -+ -+static void nslu2_flash_add(struct mtd_info *mtd) { -+ if (strcmp(mtd->name, "RedBoot") == 0) { -+ size_t retlen; -+ int err; -+ /* the mac addr is at a known offset */ -+ err = mtd->read(mtd, 0x3FFB0, 6, &retlen, (u8 *) &mac.sa_data); -+ if (err != 0 || retlen != 6) -+ printk(KERN_ERR "nslu2: mac addr read failed\n"); -+ } -+} -+ -+static void nslu2_flash_remove(struct mtd_info *mtd) { -+} -+ -+static struct mtd_notifier nslu2_flash_notifier = { -+ .add = nslu2_flash_add, -+ .remove = nslu2_flash_remove, -+}; -+ -+ -+static int nslu2_netdev_event(struct notifier_block *this, -+ unsigned long event, void *ptr) -+{ -+ struct net_device *dev = ptr; -+ -+ /* identify the ixp4xx eth, port 1 */ -+ if (dev->dev_addr[1] != 0x02 || dev->dev_addr[2] != 0xB3 -+ || dev->dev_addr[5] != 0x01) -+ return NOTIFY_DONE; -+ -+ if (event == NETDEV_REGISTER && is_valid_ether_addr(mac.sa_data)) { -+ mac.sa_family = dev->type; -+ dev_set_mac_address(dev, &mac); -+ printk(KERN_INFO -+ "ixp400_eth: MAC address now set to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x for port 0\n", -+ mac.sa_data[0], mac.sa_data[1], mac.sa_data[2], -+ mac.sa_data[3], mac.sa_data[4], mac.sa_data[5]); -+ } -+ -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block nslu2_netdev_notifier = { -+ .notifier_call = nslu2_netdev_event, -+}; -+ - static void __init nslu2_init(void) - { - /* The NSLU2 has a 33MHz crystal on board - 1.01% different -@@ -124,6 +180,12 @@ static void __init nslu2_init(void) - */ - ixp4xx_set_board_tick_rate(66000000); - -+ /* The flash has an ethernet MAC embedded in it which we need, -+ * that is all this notifier does. -+ */ -+ register_mtd_user(&nslu2_flash_notifier); -+ register_netdevice_notifier(&nslu2_netdev_notifier); -+ - ixp4xx_sys_init(); - - nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-maclist.patch b/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-maclist.patch deleted file mode 100644 index a280a49e6f..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/92-nslu2-maclist.patch +++ /dev/null @@ -1,81 +0,0 @@ - arch/arm/mach-ixp4xx/Kconfig | 1 - arch/arm/mach-ixp4xx/nslu2-setup.c | 39 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 40 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-03-08 10:33:10.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-03-08 10:33:14.000000000 +0100 -@@ -16,11 +16,14 @@ - #include <linux/kernel.h> - #include <linux/serial.h> - #include <linux/serial_8250.h> -+#include <linux/mtd/mtd.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> - #include <asm/mach/flash.h> - -+#include <net/maclist.h> -+ - static struct flash_platform_data nslu2_flash_data = { - .map_name = "cfi_probe", - .width = 2, -@@ -117,6 +120,37 @@ static void nslu2_power_off(void) - gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH); - } - -+/* -+ * When the RedBoot partition is added the MAC address is read from -+ * it. -+ */ -+static void nslu2_flash_add(struct mtd_info *mtd) { -+ if (strcmp(mtd->name, "RedBoot") == 0) { -+ size_t retlen; -+ u_char mac[6]; -+ -+ /* The MAC is at a known offset... */ -+ if (mtd->read(mtd, 0x3FFB0, 6, &retlen, mac) == 0 && retlen == 6) { -+ printk(KERN_INFO "NSLU2 MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", -+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); -+ maclist_add(mac); -+ } else { -+ printk(KERN_ERR "NSLU2 MAC: read failed\n"); -+ } -+ } -+} -+ -+/* -+ * Nothing to do on remove at present. -+ */ -+static void nslu2_flash_remove(struct mtd_info *mtd) { -+} -+ -+static struct mtd_notifier nslu2_flash_notifier = { -+ .add = nslu2_flash_add, -+ .remove = nslu2_flash_remove, -+}; -+ - static void __init nslu2_init(void) - { - /* The NSLU2 has a 33MHz crystal on board - 1.01% different -@@ -124,6 +158,11 @@ static void __init nslu2_init(void) - */ - ixp4xx_set_board_tick_rate(66000000); - -+ /* The flash has an ethernet MAC embedded in it which we need, -+ * that is all this notifier does. -+ */ -+ register_mtd_user(&nslu2_flash_notifier); -+ - ixp4xx_sys_init(); - - nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/Kconfig 2006-03-08 10:33:12.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/Kconfig 2006-03-08 10:33:22.000000000 +0100 -@@ -11,6 +11,7 @@ comment "IXP4xx Platforms" - config MACH_NSLU2 - bool - prompt "Linksys NSLU2" -+ select MACLIST - help - Say 'Y' here if you want your kernel to support Linksys's - NSLU2 NAS device. For more information on this platform, diff --git a/packages/linux/ixp4xx-kernel/2.6.16/94-loft-setup.patch b/packages/linux/ixp4xx-kernel/2.6.16/94-loft-setup.patch deleted file mode 100644 index 6f82262967..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/94-loft-setup.patch +++ /dev/null @@ -1,214 +0,0 @@ - ---- - arch/arm/mach-ixp4xx/ixdp425-setup.c | 173 ++++++++++++++++++++++++++++++++--- - 1 file changed, 163 insertions(+), 10 deletions(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-03-27 03:08:59.000000000 +0200 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/ixdp425-setup.c 2006-03-27 03:40:03.000000000 +0200 -@@ -11,20 +11,26 @@ - #include <linux/kernel.h> - #include <linux/init.h> - #include <linux/device.h> --#include <linux/serial.h> --#include <linux/tty.h> - #include <linux/serial_8250.h> --#include <linux/slab.h> -- --#include <asm/types.h> -+#include <linux/i2c.h> -+#include <linux/eeprom.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> - #include <asm/setup.h> - #include <asm/memory.h> - #include <asm/hardware.h> - #include <asm/mach-types.h> --#include <asm/irq.h> - #include <asm/mach/arch.h> - #include <asm/mach/flash.h> - -+#ifdef CONFIG_LEDS_CLASS -+#include <linux/leds.h> -+#endif -+ -+#ifdef CONFIG_MACLIST -+#include <net/maclist.h> -+#endif -+ - static struct flash_platform_data ixdp425_flash_data = { - .map_name = "cfi_probe", - .width = 2, -@@ -176,22 +182,169 @@ MACHINE_START(AVILA, "Gateworks Avila Ne - MACHINE_END - #endif - -+#ifdef CONFIG_MACH_LOFT -+#ifdef CONFIG_LEDS_CLASS -+static struct resource loft_led_resources[] = { -+ { -+ .name = "ready", /* green led, also J8 pin 7 */ -+ .start = 3, /* FIXME use #define */ -+ .end = 3, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+}; -+ -+static struct platform_device loft_leds = { -+ .name = "IXP4XX-GPIO-LED", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(loft_led_resources), -+ .resource = loft_led_resources, -+}; -+#endif -+ - /* - * Loft is functionally equivalent to Avila except that it has a - * different number for the maximum PCI devices. The MACHINE -- * structure below is identical to Avila except for the comment. -+ * structure below is derived from the Avila one (and may, in -+ * fact, be useful on Avila in general). -+ * -+ * The loft init registers a notifier on the on-board EEPROM to -+ * detect the MAC addresses. -+ * NOTE: this probably works for all Gateworks Avila boards and -+ * maybe the ixdp425 too. -+ * -+ * When the EEPROM is added the MAC address are read from it. - */ --#ifdef CONFIG_MACH_LOFT -+ -+#if defined(CONFIG_SENSORS_EEPROM) -+static unsigned char loft_macs[12]; -+ -+static int loft_eeprom_event(struct notifier_block *this, -+ unsigned long event, void *ptr) -+{ -+ struct eeprom_data *data = ptr; -+ -+ /* The MACs are the first 12 bytes in the eeprom at address 0x51 */ -+ if (event == EEPROM_REGISTER && data->client.addr == 0x51) -+ data->attr->read(&data->client.dev.kobj, loft_macs, 0, 12); -+ -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block loft_eeprom_notifier = { -+ .notifier_call = loft_eeprom_event, -+}; -+ -+static int loft_netdev_event(struct notifier_block *this, -+ unsigned long event, void *ptr) -+{ -+ struct net_device *dev = ptr; -+ unsigned char *hwaddr = NULL; -+ -+ /* identify the ixp4xx eth */ -+ if (dev->dev_addr[1] != 0x02 || dev->dev_addr[2] != 0xB3) -+ return NOTIFY_DONE; -+ -+ if (event != NETDEV_REGISTER) -+ return NOTIFY_DONE; -+ -+ /* identify the port */ -+ if (dev->dev_addr[5] == 0x01) -+ hwaddr = &loft_macs[0]; -+ else if (dev->dev_addr[5] == 0x02) -+ hwaddr = &loft_macs[6]; -+ -+ if (hwaddr && is_valid_ether_addr(hwaddr)) { -+ struct sockaddr addr; -+ addr.sa_family = dev->type; -+ memcpy(addr.sa_data, hwaddr, ETH_ALEN); -+ dev_set_mac_address(dev, &addr); -+ } -+ -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block loft_netdev_notifier = { -+ .notifier_call = loft_netdev_event, -+}; -+#endif -+ -+static void __init loft_init(void) -+{ -+ ixdp425_init(); -+ -+#ifdef CONFIG_LEDS_CLASS -+ /* We don't care if this fails. */ -+ (void)platform_device_register(&loft_leds); -+#endif -+ /* The EEPROM has two ethernet MACs embedded in it which we need, -+ * that is all this notifier does. -+ */ -+#ifdef CONFIG_SENSORS_EEPROM -+ register_eeprom_notifier(&loft_eeprom_notifier); -+ register_netdevice_notifier(&loft_netdev_notifier); -+#endif -+} -+ -+/* -+ * Loft bootstrap may pass in parameters, if these contain an -+ * ATAG_MEM and it appears valid (not the 16MByte one in the -+ * setup/kernel.c default) we use it, otherwise a 64MByte -+ * setting is forced here, this may be overridden on the -+ * command line. -+ */ -+static void __init loft_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+{ -+ /* Put Loft specific known-required-for-certain stuff here, leave -+ * a trailing space! -+ */ -+ static char loft_command_line[] = -+ "root=/dev/mtdblock2 rw rootfstype=jffs2 init=/linuxrc " -+ "rtc-ds1672.probe=0,0x68 " -+ CONFIG_CMDLINE; -+ -+ int memtag = 0; -+ -+ /* The Loft typically has one bank of 64MByte memory. -+ * NOTE: setting nr_banks != 0 causes kernel/setup.c to remove -+ * the mem tags from the tag list, so if there is an entry -+ * there don't remove it! -+ */ -+ if (tags->hdr.tag == ATAG_CORE) do { -+ tags = tag_next(tags); -+ printk(KERN_NOTICE "ATAG[0x%x] size %d\n", tags->hdr.tag, tags->hdr.size); -+ if (tags->hdr.tag == ATAG_MEM && tags->hdr.size == tag_size(tag_mem32) && -+ (tags->u.mem.start != 0 || tags->u.mem.size != (16*1024*1024))) { -+ memtag = 1; -+ printk(KERN_NOTICE " ATAG_MEM base %x, size %dMB\n", -+ tags->u.mem.start, -+ tags->u.mem.size / (1024*1024)); -+ } -+ } while (tags->hdr.size); -+ -+ if (!memtag) { -+ mi->nr_banks = 1; -+ mi->bank[0].start = 0; -+ mi->bank[0].size = (64*1024*1024); -+ mi->bank[0].node = PHYS_TO_NID(0); -+ } -+ -+ /* A command line in the ATAG list will override this one, -+ * as is intended. -+ */ -+ strlcpy(*cmdline, loft_command_line, COMMAND_LINE_SIZE); -+} -+ - MACHINE_START(LOFT, "Giant Shoulder Inc Loft board") - /* Maintainer: Tom Billman <kernel@giantshoulderinc.com> */ - .phys_ram = PHYS_OFFSET, - .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, - .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .fixup = loft_fixup, - .map_io = ixp4xx_map_io, - .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, - .boot_params = 0x0100, -- .init_machine = ixdp425_init, -+ .init_machine = loft_init, - MACHINE_END - #endif -- diff --git a/packages/linux/ixp4xx-kernel/2.6.16/94-nslu2-setup.patch b/packages/linux/ixp4xx-kernel/2.6.16/94-nslu2-setup.patch deleted file mode 100644 index 3effbc7711..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/94-nslu2-setup.patch +++ /dev/null @@ -1,74 +0,0 @@ -Include a fixup machine start function in nslu2-setup.c to handle -the command line and memory setup parameters which are not specifiable -in the boot loader. - -Signed-off-by: John Bowler <jbowler@acm.org> - - arch/arm/mach-ixp4xx/nslu2-setup.c | 45 ++++++++++++++++++++++++++++++++++++- - 1 file changed, 44 insertions(+), 1 deletion(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-23 18:31:00.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-23 18:31:04.000000000 +0100 -@@ -18,6 +18,8 @@ - #include <linux/serial_8250.h> - #include <linux/mtd/mtd.h> - -+#include <asm/setup.h> -+#include <asm/memory.h> - #include <asm/mach-types.h> - #include <asm/mach/arch.h> - #include <asm/mach/flash.h> -@@ -174,11 +176,52 @@ static void __init nslu2_init(void) - platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); - } - -+/* -+ * NSLU2 RedBoot passes garbage atag/parameter values because it copies -+ * the kernel zImage on top of the parameter list before branching into -+ * the zImage. The machine description causes the ATAG list to be -+ * skipped (by setting boot_params to 0) and this code fixes up the -+ * memory info and command line by supplying a command line with the -+ * NSLU2 specific config prepended. -+ * -+ * NOTE: the startup sequence is: -+ * 1) Call the machine fixup -+ * 2) Parse the ATAG list, the ATAG_CMDLINE is copied in -+ * to default_command_line which is the value of *from -+ * 3) Parse the command line in *from (*not* -+ * default_command_line unless they are the same!) -+ * -+ * Setting mi->nr_banks causes (2) to 'squash' (set to ATAG_NONE) -+ * any ATAG_MEM tags, but mem= command line options cause nr_banks -+ * to be reset to 0 (on the first mem=) -+ */ -+static char nslu2_command_line[] __initdata = -+ "root=/dev/mtdblock4 rootfstype=jffs2 init=/linuxrc " -+ "rtc-x1205.probe=0,0x6f " -+ CONFIG_CMDLINE; -+ -+static void __init nslu2_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+{ -+ /* The NSLU2 has one bank of 32MByte memory. -+ * NOTE: to make a 'fatslug' work append the appropriate -+ * mem= to the CONFIG_CMDLINE - this will override the -+ * setting below. -+ */ -+ mi->nr_banks=1; -+ mi->bank[0].start = 0; -+ mi->bank[0].size = (32*1024*1024); -+ mi->bank[0].node = PHYS_TO_NID(0); -+ -+ strlcpy(*cmdline, nslu2_command_line, COMMAND_LINE_SIZE); -+} -+ - MACHINE_START(NSLU2, "Linksys NSLU2") - /* Maintainer: www.nslu2-linux.org */ - .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, - .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, -- .boot_params = 0x00000100, -+ .boot_params = 0, /* because they are garbage - see above */ -+ .fixup = nslu2_fixup, - .map_io = ixp4xx_map_io, - .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, diff --git a/packages/linux/ixp4xx-kernel/2.6.16/951-ixp4xx-leds-cpu-activity.patch b/packages/linux/ixp4xx-kernel/2.6.16/951-ixp4xx-leds-cpu-activity.patch deleted file mode 100644 index 6d4c53026c..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/951-ixp4xx-leds-cpu-activity.patch +++ /dev/null @@ -1,596 +0,0 @@ -This patches the new LEDs code to add cpu activity and -inactivity triggers to the timer triggers. The new triggers -set the LED with the trigger to different states (on, -flashing or off) according to whether or not all CPUs -are idle. - -Signed-off-by: John Bowler <jbowler@acm.org> - ---- - arch/arm/kernel/process.c | 11 - drivers/leds/Kconfig | 9 - drivers/leds/Makefile | 1 - drivers/leds/ledtrig-cpu.c | 501 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/leds.h | 9 - 5 files changed, 531 insertions(+) - ---- linux-ixp4xx.orig/arch/arm/kernel/process.c 2006-02-21 00:53:28.000000000 +0100 -+++ linux-ixp4xx/arch/arm/kernel/process.c 2006-02-21 01:03:33.000000000 +0100 -@@ -27,6 +27,7 @@ - #include <linux/kallsyms.h> - #include <linux/init.h> - #include <linux/cpu.h> -+#include <linux/leds.h> - #include <linux/elfcore.h> - - #include <asm/leds.h> -@@ -80,6 +81,12 @@ void (*pm_power_off)(void); - EXPORT_SYMBOL(pm_power_off); - - /* -+ * CPU activity indicator. -+ */ -+void (*leds_idle)(int is_idle); -+EXPORT_SYMBOL(leds_idle); -+ -+/* - * This is our default idle handler. We need to disable - * interrupts here to ensure we don't miss a wakeup call. - */ -@@ -120,8 +127,12 @@ void cpu_idle(void) - if (!idle) - idle = default_idle; - leds_event(led_idle_start); -+ if (leds_idle) -+ leds_idle(1); - while (!need_resched()) - idle(); -+ if (leds_idle) -+ leds_idle(0); - leds_event(led_idle_end); - preempt_enable_no_resched(); - schedule(); ---- linux-ixp4xx.orig/drivers/leds/Kconfig 2006-02-21 00:58:36.000000000 +0100 -+++ linux-ixp4xx/drivers/leds/Kconfig 2006-02-21 01:03:33.000000000 +0100 -@@ -66,5 +66,14 @@ config LEDS_TRIGGER_TIMER - This allows LEDs to be controlled by a programmable timer - via sysfs. If unsure, say Y. - -+config LEDS_TRIGGER_CPU_ACTIVITY -+ tristate "LED CPU activity trigger" -+ depends LEDS_TRIGGER_TIMER -+ help -+ This allows LEDs to be set to show cpu activity via sysfs. -+ The LED will blink when the cpu is active and stay steady -+ (on or off according to the trigger selected) when idle. -+ If unsure, say Y. -+ - endmenu - ---- linux-ixp4xx.orig/drivers/leds/Makefile 2006-02-21 00:58:36.000000000 +0100 -+++ linux-ixp4xx/drivers/leds/Makefile 2006-02-21 01:03:33.000000000 +0100 -@@ -13,3 +13,4 @@ obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o - - # LED Triggers - obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o -+obj-$(CONFIG_LEDS_TRIGGER_CPU_ACTIVITY) += ledtrig-cpu.o ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/ledtrig-cpu.c 2006-02-21 01:08:57.000000000 +0100 -@@ -0,0 +1,501 @@ -+/* -+ * LEDs CPU activity trigger -+ * -+ * Author: John Bowler <jbowler@acm.org> -+ * -+ * Copyright (c) 2006 John Bowler -+ * -+ * Permission is hereby granted, free of charge, to any -+ * person obtaining a copy of this software and associated -+ * documentation files (the "Software"), to deal in the -+ * Software without restriction, including without -+ * limitation the rights to use, copy, modify, merge, -+ * publish, distribute, sublicense, and/or sell copies of -+ * the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the -+ * following conditions: -+ * -+ * The above copyright notice and this permission notice -+ * shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/ctype.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/spinlock.h> -+#include <linux/timer.h> -+#include <linux/device.h> -+ -+#include <linux/leds.h> -+#include "leds.h" -+ -+//#include <linux/list.h> -+//#include <linux/sysdev.h> -+ -+ -+/* -+ * To simplify this the LED state is given for each case of -+ * CPU state - idle or active. The LED can be: -+ * -+ * off -+ * flash - slow for idle, fast (flicker) for active -+ * on -+ * -+ * This gives two useless states - off/off and on/on -+ */ -+typedef enum cpu_trigger_led_state { -+ cpu_led_off, -+ cpu_led_flash, -+ cpu_led_on, -+ cpu_led_invalid -+} cpu_trigger_led_state; -+ -+static const char *const cpu_trigger_names[] = { -+ "off", -+ "flash", -+ "on", -+ "invalid" -+}; -+ -+/* Forward declaration - this is called back when an LED property -+ * is changed. -+ */ -+static void leds_cpu_trigger_state_change(void); -+ -+/* -+ * These constants define the actual mark/space of the flashing -+ * in jiffies. msecs_to_jiffies rounds up and is compile time -+ * evaluable for constant arguments. Writing the ?: stuff below -+ * this way ensures the compiler doesn't think it needs to -+ * compile in the math of msecs_to_jiffies. -+ * -+ * These values have been determined by experiment to work well -+ * for the ready/status LED on a LinkSys NSLU2 (light piped) and -+ * for the user LED on a Loft (Gateway Avila variant) board where -+ * the LED was directly visible. Light Output Varies Everywhere. -+ */ -+#define LEDS_CPU_ACTIVE_MARK msecs_to_jiffies(40) -+#define LEDS_CPU_IDLE_MARK msecs_to_jiffies(800) -+#define LEDS_CPU_ACTIVE_SPACE msecs_to_jiffies(60) -+#define LEDS_CPU_IDLE_SPACE msecs_to_jiffies(800) -+ -+ -+/* -+ * Individual LEDs ------------------------------------------------------------ -+ */ -+struct cpu_trigger_data { -+ cpu_trigger_led_state active; /* Behaviour when the CPU is active. */ -+ cpu_trigger_led_state idle; /* Behaviour when the CPU is idle. */ -+}; -+ -+/* -+ * LED state change - called when the state of a single LED might -+ * have changed. Returns true if the LED is blinking. The argument -+ * is the blink state - the brightness of the blinking LED. -+ */ -+static int leds_cpu_trigger_led_state_change(struct led_classdev *led, -+ int is_active, enum led_brightness brightness) -+{ -+ int is_blinking = 0; -+ -+ write_lock(&led->lock); -+ { -+ struct cpu_trigger_data *data = led->trigger_data; -+ -+ /* Find the new brightness for the LED, if the LED is -+ * set to flash then the brightness passed in is the -+ * required value. -+ */ -+ if (likely(data != 0)) -+ switch (is_active ? data->active : data->idle) { -+ case cpu_led_off: brightness = LED_OFF; break; -+ case cpu_led_flash: is_blinking = 1; break; -+ case cpu_led_on: brightness = LED_FULL; break; -+ } -+ else -+ brightness = is_active ? LED_FULL : LED_OFF; -+ -+ led_set_brightness(led, brightness); -+ } -+ write_unlock(&led->lock); -+ -+ return is_blinking; -+} -+ -+/* -+ * sysfs properties, the property is output at an list of the -+ * values with the current setting enclosed in [] -+ */ -+static ssize_t leds_cpu_trigger_show_prop(struct class_device *dev, char *buf, -+ size_t where) -+{ -+ struct led_classdev *led = dev->class_data; -+ cpu_trigger_led_state item = cpu_led_invalid, i; -+ char *next; -+ -+ read_lock(&led->lock); -+ { -+ if (likely(led->trigger_data != 0)) -+ item = *(const cpu_trigger_led_state*)( -+ led->trigger_data + where); -+ } -+ read_unlock(&led->lock); -+ -+ for (i=0, next=buf; i<cpu_led_invalid; ++i) { -+ const char *name = cpu_trigger_names[i]; -+ size_t len = strlen(name); -+ -+ if (i == item) -+ *next++ = '['; -+ memcpy(next, name, len); -+ next += len; -+ if (i == item) -+ *next++ = ']'; -+ *next++ = ' '; -+ } -+ -+ next[-1] = '\n'; -+ *next++ = 0; -+ -+ return next - buf; -+} -+ -+static ssize_t leds_cpu_trigger_show_active(struct class_device *dev, char *buf) -+{ -+ return leds_cpu_trigger_show_prop(dev, buf, -+ offsetof(struct cpu_trigger_data, active)); -+} -+ -+static ssize_t leds_cpu_trigger_show_idle(struct class_device *dev, char *buf) -+{ -+ return leds_cpu_trigger_show_prop(dev, buf, -+ offsetof(struct cpu_trigger_data, idle)); -+} -+ -+/* -+ * Any matching leading substring selects a property - so "onoffonoff" -+ * sets the property to off. -+ */ -+static ssize_t leds_cpu_trigger_store_prop(struct class_device *dev, -+ const char *buf, size_t size, size_t where) -+{ -+ size_t rc = 0; -+ cpu_trigger_led_state value = 0/*sic*/; -+ struct led_classdev *led; -+ -+ /* ignore space characters before the value. */ -+ while (rc < size && isspace(buf[rc])) -+ ++rc; -+ if (rc >= size) -+ return rc; -+ -+ /* look for a simple match against the trigger name, case -+ * sensitive. -+ */ -+ do { -+ const char *name = cpu_trigger_names[value]; -+ size_t len = strlen(name); -+ if (len <= size && memcmp(buf+rc, name, len) == 0) { -+ rc = len; -+ break; -+ } -+ if (++value >= cpu_led_invalid) -+ return -EINVAL; -+ } while (1); -+ -+ led = dev->class_data; -+ write_lock(&led->lock); -+ { -+ if (likely(led->trigger_data != 0)) -+ *(cpu_trigger_led_state*)( -+ led->trigger_data + where) = value; -+ -+ } -+ write_unlock(&led->lock); -+ -+ return rc; -+} -+ -+static ssize_t leds_cpu_trigger_store_active(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ ssize_t rc = leds_cpu_trigger_store_prop(dev, buf, size, -+ offsetof(struct cpu_trigger_data, active)); -+ /* -+ * At least one CPU must be active (otherwise who is doing this?) -+ * Call down into the global state below to cause an update -+ * to happen now. -+ */ -+ leds_cpu_trigger_state_change(); -+ return rc; -+} -+ -+static ssize_t leds_cpu_trigger_store_idle(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ return leds_cpu_trigger_store_prop(dev, buf, size, -+ offsetof(struct cpu_trigger_data, idle)); -+} -+ -+static CLASS_DEVICE_ATTR(active, 0644, leds_cpu_trigger_show_active, -+ leds_cpu_trigger_store_active); -+ -+static CLASS_DEVICE_ATTR(idle, 0644, leds_cpu_trigger_show_idle, -+ leds_cpu_trigger_store_idle); -+ -+/* -+ * Activate and deactivate are called on individual LEDs when the -+ * LED trigger property is changed. The LED write lock is held. -+ */ -+static void leds_cpu_trigger_activate(struct led_classdev *led) -+{ -+ /* -+ * The initial setting of the trigger is simple CPU activity -+ * with the LED off for idle and on for active. Consequently -+ * there is no need to mess with the global state initially, -+ * we know the CPU is active at this moment! -+ */ -+ struct cpu_trigger_data *data = kmalloc(sizeof *data, GFP_KERNEL); -+ if (unlikely(data == 0)) -+ return; -+ -+ data->active = cpu_led_on; -+ data->idle = cpu_led_off; -+ led->trigger_data = data; -+ -+ class_device_create_file(led->class_dev, &class_device_attr_active); -+ class_device_create_file(led->class_dev, &class_device_attr_idle); -+ -+ led_set_brightness(led, LED_FULL); -+} -+ -+static void leds_cpu_trigger_deactivate(struct led_classdev *led) -+{ -+ struct cpu_trigger_data *data = led->trigger_data; -+ if (likely(data != 0)) { -+ led_set_brightness(led, LED_OFF); -+ -+ class_device_remove_file(led->class_dev, &class_device_attr_idle); -+ class_device_remove_file(led->class_dev, &class_device_attr_active); -+ -+ led->trigger_data = 0; -+ kfree(data); -+ } -+} -+ -+ -+/* -+ * Global state -------------------------------------------------------------- -+ * -+ * This is global because the CPU state is global and we only need one timer to -+ * do this stuff. -+ */ -+typedef struct leds_cpu_trigger_data { -+ struct led_trigger trigger; /* the lock in here protects everything */ -+ struct timer_list timer; -+ unsigned long last_active_time; /* record of last jiffies */ -+ unsigned long last_idle_time; /* record of last jiffies */ -+ int count_active; /* number of active CPUs */ -+} leds_cpu_trigger_data; -+ -+/* -+ * Mark state - uses the current time (jiffies) to work out -+ * whether this is a mark or space. -+ */ -+static int leds_cpu_trigger_mark(struct leds_cpu_trigger_data *data, -+ unsigned long now) { -+ if (data->count_active > 0) { -+ unsigned long elapsed = now - data->last_active_time; -+ elapsed %= LEDS_CPU_ACTIVE_SPACE + LEDS_CPU_ACTIVE_MARK; -+ data->last_active_time = now - elapsed; -+ return elapsed > LEDS_CPU_ACTIVE_SPACE; -+ } else { -+ unsigned long elapsed = now - data->last_idle_time; -+ elapsed %= LEDS_CPU_IDLE_SPACE + LEDS_CPU_IDLE_MARK; -+ data->last_idle_time = now - elapsed; -+ return elapsed > LEDS_CPU_IDLE_SPACE; -+ } -+} -+ -+ -+/* -+ * State change - given information about the nature of the -+ * (possible) state change call up to each LED to adjust its -+ * state. Returns true if any LED is blinking. The lock -+ * must be held (a read lock is adequate). -+ */ -+static int leds_cpu_trigger_scan_leds(struct leds_cpu_trigger_data *data, -+ unsigned long now) -+{ -+ int blinking = 0; -+ const int active = data->count_active > 0; -+ const enum led_brightness brightness = -+ leds_cpu_trigger_mark(data, now) ? LED_FULL : LED_OFF; -+ struct list_head *entry; -+ -+ list_for_each(entry, &data->trigger.led_cdevs) { -+ struct led_classdev *led = -+ list_entry(entry, struct led_classdev, trig_list); -+ -+ blinking |= leds_cpu_trigger_led_state_change(led, -+ active, brightness); -+ } -+ -+ return blinking; -+} -+ -+/* -+ * Set the timer correctly according to the current state, the lock -+ * must be held for write. -+ */ -+static void leds_cpu_trigger_set_timer(struct leds_cpu_trigger_data *state, -+ unsigned long now) -+{ -+ unsigned long next; -+ if (state->count_active > 0) { -+ next = state->last_active_time; -+ if (now - next > LEDS_CPU_ACTIVE_SPACE) -+ next += LEDS_CPU_ACTIVE_MARK; -+ next += LEDS_CPU_ACTIVE_SPACE; -+ } else { -+ next = state->last_idle_time; -+ if (now - next > LEDS_CPU_IDLE_SPACE) -+ next += LEDS_CPU_IDLE_MARK; -+ next += LEDS_CPU_IDLE_SPACE; -+ } -+ mod_timer(&state->timer, next); -+} -+ -+/* -+ * The timer callback if the LED is currently flashing, the callback -+ * calls the state change function and, if that returns true, meaning -+ * that at least one LED is still blinking, the timer is restarted -+ * with the correct timeout. -+ */ -+static void leds_cpu_trigger_timer_callback(unsigned long data) -+{ -+ struct leds_cpu_trigger_data *state = -+ (struct leds_cpu_trigger_data *)data; -+ -+ write_lock(&state->trigger.leddev_list_lock); -+ { -+ unsigned long now = jiffies; -+ -+ /* If at least one LED is set to flash; set the timer -+ * again (this won't reset the timer set within the -+ * idle loop). -+ */ -+ if (leds_cpu_trigger_scan_leds(state, now)) -+ leds_cpu_trigger_set_timer(state, now); -+ } -+ write_unlock(&state->trigger.leddev_list_lock); -+} -+ -+ -+/* -+ * There is one global control structure, one timer and one set -+ * of state for active CPUs shared across all the LEDs. Individual -+ * LEDs say how this state to be handled. It is currently *not* -+ * possible to show per-cpu activity on individual LEDs, the code -+ * maintains a count of active CPUs and the state is only 'idle' -+ * if all CPUs are idle. -+ */ -+static struct leds_cpu_trigger_data leds_cpu_trigger = { -+ .trigger = { -+ .name = "cpu", -+ .activate = leds_cpu_trigger_activate, -+ .deactivate = leds_cpu_trigger_deactivate, -+ } , -+ .timer = TIMER_INITIALIZER(leds_cpu_trigger_timer_callback, 0, -+ (unsigned long)&leds_cpu_trigger), -+ .last_active_time = 0, -+ .last_idle_time = 0, -+ .count_active = 0, -+}; -+ -+/* -+ * State change - callback from an individual LED on a property change which -+ * might require a redisplay. -+ */ -+static void leds_cpu_trigger_state_change() { -+ write_lock(&leds_cpu_trigger.trigger.leddev_list_lock); -+ { -+ unsigned long now = jiffies; -+ -+ if (leds_cpu_trigger_scan_leds(&leds_cpu_trigger, now) && -+ !timer_pending(&leds_cpu_trigger.timer)) -+ leds_cpu_trigger_set_timer(&leds_cpu_trigger, now); -+ } -+ write_unlock(&leds_cpu_trigger.trigger.leddev_list_lock); -+} -+ -+/* -+ * Called from every CPU at the start and end of the idle loop. -+ * The active count is initially 0, even though CPUs are running, -+ * so the code below must check for the resultant underflow. -+ * -+ * If the idle behaviour is 'flash' then when the timer times out -+ * it will take the CPU out of idle, set the active state (which -+ * may also be flash), drop back into idle and reset the timer to -+ * the idle timeout... -+ */ -+static void leds_cpu_trigger_idle(int is_idle) -+{ -+ write_lock(&leds_cpu_trigger.trigger.leddev_list_lock); -+ if ((is_idle && leds_cpu_trigger.count_active > 0 && -+ --leds_cpu_trigger.count_active == 0) || -+ (!is_idle && leds_cpu_trigger.count_active < num_online_cpus() && -+ ++leds_cpu_trigger.count_active == 1)) { -+ unsigned long now = jiffies; -+ -+ /* State change - the system just became idle or active, -+ * call the del_timer first in an attempt to minimise -+ * getting a timer interrupt which will take us unnecessarily -+ * out of idle (this doesn't matter). -+ */ -+ del_timer(&leds_cpu_trigger.timer); -+ if (leds_cpu_trigger_scan_leds(&leds_cpu_trigger, now)) -+ leds_cpu_trigger_set_timer(&leds_cpu_trigger, now); -+ } -+ write_unlock(&leds_cpu_trigger.trigger.leddev_list_lock); -+} -+ -+/* -+ * Module init and exit - register the trigger, then store -+ * the idle callback in the arch-specific global. For this -+ * module to link (into the kernel) or load (into a running -+ * kernel) the architecture must define the leds_idle global. -+ */ -+static int __init leds_cpu_trigger_init(void) -+{ -+ int rc = led_trigger_register(&leds_cpu_trigger.trigger); -+ leds_idle = leds_cpu_trigger_idle; -+ return rc; -+} -+module_init(leds_cpu_trigger_init); -+ -+static void __exit leds_cpu_trigger_exit(void) -+{ -+ leds_idle = 0; -+ del_timer_sync(&leds_cpu_trigger.timer); -+ led_trigger_unregister(&leds_cpu_trigger.trigger); -+} -+module_exit(leds_cpu_trigger_exit); -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("CPU activity LED trigger"); -+MODULE_LICENSE("MIT"); ---- linux-ixp4xx.orig/include/linux/leds.h 2006-02-21 00:54:33.000000000 +0100 -+++ linux-ixp4xx/include/linux/leds.h 2006-02-21 01:03:33.000000000 +0100 -@@ -102,4 +102,13 @@ void led_trigger_event(struct led_trigge - #define led_trigger_event(x, y) do {} while(0) - - #endif -+ -+/* -+ * CPU activity indication. -+ */ -+/* Idle callback - call with is_idle==1 at the start of the idle loop -+ * and with is_idle==0 at the end. This symbol must be defined by -+ * the arch core to be able to use LEDS_TRIGGER_CPU_ACTIVITY -+ */ -+extern void (*leds_idle)(int is_idle); - #endif /* __LINUX_LEDS_H_INCLUDED */ diff --git a/packages/linux/ixp4xx-kernel/2.6.16/96-nas100d-leds.patch b/packages/linux/ixp4xx-kernel/2.6.16/96-nas100d-leds.patch deleted file mode 100644 index 60b6bbd4c9..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/96-nas100d-leds.patch +++ /dev/null @@ -1,82 +0,0 @@ -NEW_LEDS support for the IOMega NAS100D - -Signed-off-by: John Bowler <jbowler@acm.org> - ---- - arch/arm/mach-ixp4xx/nas100d-setup.c | 43 ++++++++++++++++++++++++++++++++++- - 1 file changed, 42 insertions(+), 1 deletion(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-27 13:45:22.000000000 +0200 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nas100d-setup.c 2006-03-27 13:46:00.000000000 +0200 -@@ -18,6 +18,7 @@ - #include <linux/mtd/mtd.h> - #include <linux/netdevice.h> - #include <linux/etherdevice.h> -+#include <linux/leds.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -41,6 +42,36 @@ static struct platform_device nas100d_fl - .resource = &nas100d_flash_resource, - }; - -+#ifdef CONFIG_LEDS_CLASS -+static struct resource nas100d_led_resources[] = { -+ { -+ .name = "wlan", /* green led */ -+ .start = 0, -+ .end = 0, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "ready", /* blue power led (off is flashing!) */ -+ .start = 15, -+ .end = 15, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "disk", /* yellow led */ -+ .start = 3, -+ .end = 3, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+}; -+ -+static struct platform_device nas100d_leds = { -+ .name = "IXP4XX-GPIO-LED", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(nas100d_led_resources), -+ .resource = nas100d_led_resources, -+}; -+#endif -+ - static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = { - .sda_pin = NAS100D_SDA_PIN, - .scl_pin = NAS100D_SCL_PIN, -@@ -99,7 +130,6 @@ static struct platform_device nas100d_ua - static struct platform_device *nas100d_devices[] __initdata = { - &nas100d_i2c_controller, - &nas100d_flash, -- &nas100d_uart, - }; - - static void nas100d_power_off(void) -@@ -187,7 +217,18 @@ static void __init nas100d_init(void) - - pm_power_off = nas100d_power_off; - -+ /* This is only useful on a modified machine, but it is valuable -+ * to have it first in order to see debug messages, and so that -+ * it does *not* get removed if platform_add_devices fails! -+ */ -+ (void)platform_device_register(&nas100d_uart); -+ - platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices)); -+ -+#ifdef CONFIG_LEDS_CLASS -+ /* We don't care whether or not this works. */ -+ (void)platform_device_register(&nas100d_leds); -+#endif - } - - /* diff --git a/packages/linux/ixp4xx-kernel/2.6.16/96-nslu2-leds.patch b/packages/linux/ixp4xx-kernel/2.6.16/96-nslu2-leds.patch deleted file mode 100644 index 7890d392b0..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/96-nslu2-leds.patch +++ /dev/null @@ -1,89 +0,0 @@ -NEW_LEDS support for the LinkSys NSLU2 - -Signed-off-by: John Bowler <jbowler@acm.org> - - arch/arm/mach-ixp4xx/nslu2-setup.c | 51 ++++++++++++++++++++++++++++++++++++- - 1 file changed, 50 insertions(+), 1 deletion(-) - ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-21 02:54:05.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/nslu2-setup.c 2006-02-21 02:54:05.000000000 +0100 -@@ -17,6 +17,9 @@ - #include <linux/mtd/mtd.h> - #include <linux/netdevice.h> - #include <linux/etherdevice.h> -+#ifdef CONFIG_LEDS_CLASS -+#include <linux/leds.h> -+#endif - - #include <asm/setup.h> - #include <asm/memory.h> -@@ -48,6 +51,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_ - .scl_pin = NSLU2_SCL_PIN, - }; - -+#ifdef CONFIG_LEDS_CLASS -+static struct resource nslu2_led_resources[] = { -+ { -+ .name = "ready", /* green led */ -+ .start = NSLU2_LED_GRN, -+ .end = NSLU2_LED_GRN, -+ .flags = IXP4XX_GPIO_HIGH, -+ }, -+ { -+ .name = "status", /* red led */ -+ .start = NSLU2_LED_RED, -+ .end = NSLU2_LED_RED, -+ .flags = IXP4XX_GPIO_HIGH, -+ }, -+ { -+ .name = "disk-1", -+ .start = NSLU2_LED_DISK1, -+ .end = NSLU2_LED_DISK1, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "disk-2", -+ .start = NSLU2_LED_DISK2, -+ .end = NSLU2_LED_DISK2, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+}; -+ -+static struct platform_device nslu2_leds = { -+ .name = "IXP4XX-GPIO-LED", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(nslu2_led_resources), -+ .resource = nslu2_led_resources, -+}; -+#endif -+ - static struct platform_device nslu2_i2c_controller = { - .name = "IXP4XX-I2C", - .id = 0, -@@ -107,7 +146,6 @@ static struct platform_device nslu2_uart - static struct platform_device *nslu2_devices[] __initdata = { - &nslu2_i2c_controller, - &nslu2_flash, -- &nslu2_uart, - &nslu2_beeper, - }; - -@@ -173,7 +211,18 @@ static void __init nslu2_init(void) - - pm_power_off = nslu2_power_off; - -+ /* This is only useful on a modified machine, but it is valuable -+ * to have it first in order to see debug messages, and so that -+ * it does *not* get removed if platform_add_devices fails! -+ */ -+ (void)platform_device_register(&nslu2_uart); -+ - platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); -+ -+#ifdef CONFIG_LEDS_CLASS -+ /* We don't care whether or not this works. */ -+ (void)platform_device_register(&nslu2_leds); -+#endif - } - - /* diff --git a/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch b/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch deleted file mode 100644 index 1c08150c45..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch +++ /dev/null @@ -1,299 +0,0 @@ ---- - drivers/scsi/Kconfig | 11 +- - drivers/scsi/Makefile | 1 - drivers/scsi/libata-core.c | 4 - drivers/scsi/pata_ixp4xx.c | 242 +++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 255 insertions(+), 3 deletions(-) - ---- linux-ixp4xx.orig/drivers/scsi/Kconfig 2006-02-24 18:13:55.000000000 +0100 -+++ linux-ixp4xx/drivers/scsi/Kconfig 2006-02-24 18:50:19.000000000 +0100 -@@ -903,11 +903,20 @@ config SCSI_PATA_WINBOND - tristate "Winbond SL82C105 PATA support" - depends on SCSI_SATA && PCI - help -- This option enables support for SL82C105 PATA devices found in the -+ This option enables support for SL82C105 PATAll devices found in the - Netwinder and some other systems - - If unsure, say N. - -+config SCSI_PATA_IXP4XX -+ tristate "IXP4XX Compact FLash support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for a Compact Flash connected on -+ the ixp4xx expansion bus. -+ -+ If unsure, say N. -+ - - config SCSI_BUSLOGIC - tristate "BusLogic SCSI support" ---- linux-ixp4xx.orig/drivers/scsi/Makefile 2006-02-24 18:13:55.000000000 +0100 -+++ linux-ixp4xx/drivers/scsi/Makefile 2006-02-24 18:16:46.000000000 +0100 -@@ -174,6 +174,7 @@ obj-$(CONFIG_SCSI_PATA_VIA) += libata.o - obj-$(CONFIG_SCSI_PATA_WINBOND) += libata.o pata_sl82c105.o - obj-$(CONFIG_SCSI_ATA_GENERIC) += libata.o ata_generic.o - obj-$(CONFIG_SCSI_PATA_LEGACY) += libata.o pata_legacy.o -+obj-$(CONFIG_SCSI_PATA_IXP4XX) += libata.o pata_ixp4xx.o - - obj-$(CONFIG_ARM) += arm/ - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/scsi/pata_ixp4xx.c 2006-02-24 18:43:02.000000000 +0100 -@@ -0,0 +1,242 @@ -+/* -+ * pata-ixp4xx.c - Legacy port PATA/SATA controller driver. -+ * Copyright (c) 2006 Tower Technologies -+ * -+ * An ATA driver to handle a Compact Flash connected -+ * to the ixp4xx expansion bus. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/libata.h> -+#include <scsi/scsi_host.h> -+ -+#define DRV_NAME "ixp4xx" -+#define DRV_VERSION "0.0.2" -+ -+/* XXX remove when converting to platform driver */ -+#define IXP4XX_IDE_BASE IXP4XX_EXP_BUS_BASE(1) -+#define IXP4XX_IDE_IRQ IRQ_IXP4XX_GPIO12 -+#define IXP4XX_IDE_CONTROL 0x1e -+#define IXP4XX_IDE_INT 12 -+#define IXP4XX_IDE_CS1_BITS 0xbfff0043 -+#define IXP4XX_IDE_PIO_MASK 0x1f -+ -+#ifdef __ARMEB__ -+#define ixp4xx_writew(data,addr) writew(data,addr) -+#define ixp4xx_readw(addr) readw(addr) -+#else -+#define ixp4xx_writew(data,addr) writew(le16_to_cpu(data),addr) -+#define ixp4xx_readw(addr) cpu_to_le16(readw(addr)) -+#endif -+ -+static struct ata_host_set *ixp4xx_host; -+ -+static unsigned int ixp4xx_mode_filter(const struct ata_port *ap, -+ struct ata_device *adev, unsigned int mask, int shift) -+{ -+ if (shift != ATA_SHIFT_PIO) -+ return 0; -+ return mask; -+} -+ -+static void ixp4xx_set_mode(struct ata_port *ap) -+{ -+ int i; -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ dev->pio_mode = XFER_PIO_0; -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+} -+ -+static void ixp4xx_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+void ixp4xx_mmio_data_xfer(struct ata_port *ap, struct ata_device *adev, -+ unsigned char *buf, unsigned int buflen, int write_data) -+{ -+ unsigned int i; -+ unsigned int words = buflen >> 1; -+ u16 *buf16 = (u16 *) buf; -+ void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; -+ -+ /* set the expansion bus in 16bit mode and restore -+ * 8 bit mode after the transaction. -+ */ -+ *IXP4XX_EXP_CS1 &= ~(0x00000001); -+ -+ /* Transfer multiple of 2 bytes */ -+ if (write_data) { -+ for (i = 0; i < words; i++) -+ writew(buf16[i], mmio); -+ } else { -+ for (i = 0; i < words; i++) -+ buf16[i] = readw(mmio); -+ } -+ -+ /* Transfer trailing 1 byte, if any. */ -+ if (unlikely(buflen & 0x01)) { -+ u16 align_buf[1] = { 0 }; -+ unsigned char *trailing_buf = buf + buflen - 1; -+ -+ if (write_data) { -+ memcpy(align_buf, trailing_buf, 1); -+ writew(le16_to_cpu(align_buf[0]), mmio); -+ } else { -+ align_buf[0] = cpu_to_le16(readw(mmio)); -+ memcpy(trailing_buf, align_buf, 1); -+ } -+ } -+ -+ *IXP4XX_EXP_CS1 |= 0x00000001; -+} -+ -+void ixp4xx_host_stop(struct ata_host_set *host_set) -+{ -+ ata_host_stop(host_set); -+ release_region(IXP4XX_IDE_BASE, 0x1000); -+} -+ -+static struct scsi_host_template ixp4xx_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations ixp4xx_port_ops = { -+ .set_mode = ixp4xx_set_mode, -+ .mode_filter = ixp4xx_mode_filter, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ixp4xx_mmio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ixp4xx_host_stop, -+ -+ .phy_reset = ixp4xx_phy_reset, -+}; -+ -+/* adjust the addresses to handle the address swizzling of the -+ * ixp4xx in little endian mode. -+ */ -+#ifndef __ARMEB__ -+void ixp4xx_fix_le_ports(struct ata_ioports *ioaddr) -+{ -+ ioaddr->data_addr ^= 0x02; -+ ioaddr->cmd_addr ^= 0x03; -+ ioaddr->altstatus_addr ^= 0x03; -+ ioaddr->ctl_addr ^= 0x03; -+ ioaddr->error_addr ^= 0x03; -+ ioaddr->feature_addr ^= 0x03; -+ ioaddr->nsect_addr ^= 0x03; -+ ioaddr->lbal_addr ^= 0x03; -+ ioaddr->lbam_addr ^= 0x03; -+ ioaddr->lbah_addr ^= 0x03; -+ ioaddr->device_addr ^= 0x03; -+ ioaddr->status_addr ^= 0x03; -+ ioaddr->command_addr ^= 0x03; -+} -+#endif -+ -+static __init int ixp4xx_init_one(unsigned long base, unsigned int irq) -+{ -+ int ret; -+ struct ata_probe_ent ae; -+ -+ memset(&ae, 0, sizeof(struct ata_probe_ent)); -+ INIT_LIST_HEAD(&ae.node); -+ -+ ae.mmio_base = ioremap(base, 0x1000); -+ if (ae.mmio_base == NULL) -+ return -ENOMEM; -+ -+ if (request_region(base, 0x1000, "pata_ixp4xx") == NULL) -+ return -EBUSY; -+ -+ ae.dev = NULL; -+ ae.port_ops = &ixp4xx_port_ops; -+ ae.sht = &ixp4xx_sht; -+ ae.n_ports = 1; -+ ae.pio_mask = IXP4XX_IDE_PIO_MASK; -+ ae.irq = irq; -+ ae.irq_flags = 0; -+ ae.host_flags = ATA_FLAG_IRQ_MASK | ATA_FLAG_MMIO; -+ -+ ae.port[0].cmd_addr = (unsigned long) ae.mmio_base; -+ ae.port[0].altstatus_addr = (unsigned long) ae.mmio_base + IXP4XX_IDE_CONTROL; -+ ae.port[0].ctl_addr = (unsigned long) ae.mmio_base + IXP4XX_IDE_CONTROL; -+ ata_std_ports(&ae.port[0]); -+ -+#ifndef __ARMEB__ -+ ixp4xx_fix_le_ports(&ae.port[0]); -+#endif -+ ret = ata_device_add(&ae); -+ if (ret == 0) -+ return -ENODEV; -+ -+ ixp4xx_host = ae.host_set; -+ return 0; -+} -+ -+static __init int ixp4xx_init(void) -+{ -+ gpio_line_config(IXP4XX_IDE_INT, IXP4XX_GPIO_IN | IXP4XX_GPIO_STYLE_ACTIVE_HIGH); -+ -+ *IXP4XX_EXP_CS1 |= IXP4XX_IDE_CS1_BITS; -+ -+ if (ixp4xx_init_one(IXP4XX_IDE_BASE, IXP4XX_IDE_INT) == 0) -+ return 0; -+ -+ return -ENODEV; -+} -+ -+static __exit void ixp4xx_exit(void) -+{ -+ if (ixp4xx_host) -+ ata_host_set_remove(ixp4xx_host); -+} -+ -+MODULE_AUTHOR("Alessandro Zummo"); -+MODULE_DESCRIPTION("low-level driver for ixp4xx CF/ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ixp4xx_init); -+module_exit(ixp4xx_exit); ---- linux-ixp4xx.orig/drivers/scsi/libata-core.c 2006-02-24 18:13:55.000000000 +0100 -+++ linux-ixp4xx/drivers/scsi/libata-core.c 2006-02-24 18:16:46.000000000 +0100 -@@ -2513,8 +2513,8 @@ static void ata_dev_set_xfermode(struct - tf.nsect = dev->xfer_mode; - - if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) { -- printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n", -- ap->id); -+ printk(KERN_ERR "ata%u: failed to set xfermode (0x%02x), disabled\n", -+ ap->id, dev->xfer_mode); - ata_port_disable(ap); - } - diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-buttons.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-buttons.patch deleted file mode 100644 index 09129ac56a..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-buttons.patch +++ /dev/null @@ -1,122 +0,0 @@ -Index: linux-2.6.15/arch/arm/mach-ixp4xx/ds101-buttons.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/ds101-buttons.c 2006-02-23 08:40:28.000000000 +0100 -@@ -0,0 +1,117 @@ -+/* -+ * arch/arm/mach-ixp4xx/ds101-buttons.c -+ * -+ * DS101 Button driver -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/module.h> -+#include <linux/reboot.h> -+#include <linux/interrupt.h> -+#include <asm/mach-types.h> -+ -+extern void ctrl_alt_del(void); -+static int usbcopyb_irqcount = 0; -+static int resetb_irqcount = 0; -+static int powerb_irqcount = 0; -+ -+static irqreturn_t ds101_usbcopy_handler(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ usbcopyb_irqcount++; -+ if (usbcopyb_irqcount > 1) /* Init creates one IRQ. Ignore it */ -+ { -+ /* The GPIO line is shared between the button and the led. -+ * Make sure the GPIO is GPIO_OUT, so we don't recieve -+ * irqs from the led going on/off. Disable the irq just in -+ * case. -+ */ -+ gpio_line_config(DS101_USBCOPYB_IRQ, DS101_GPIO_OUT); -+ disable_irq(DS101_USBCOPYB_IRQ); -+ printk(KERN_INFO "Usbcopy\n"); -+ } -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t ds101_power_handler(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ powerb_irqcount++; -+ if (powerb_irqcount > 1) -+ { -+ /* Make the power led flash */ -+ gpio_line_set(DS101_POWER_LED, DS101_GPIO_HIGH); -+ ctrl_alt_del(); -+ } -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t ds101_reset_handler(int irq, void *dev_id, struct pt_regs *regs) -+{ -+ resetb_irqcount++; -+ if (resetb_irqcount > 1) -+ { -+ machine_power_off(); -+ } -+ return IRQ_HANDLED; -+} -+ -+static int __init ds101_buttons_init(void) -+{ -+ if (!(machine_is_ds101())) -+ return 0; -+ printk(KERN_INFO "DiskStation DS101 button driver v0.2\n"); -+ gpio_line_config(DS101_POWERB_GPIO, (DS101_GPIO_IN|IRQT_FALLING)); -+ gpio_line_config(DS101_RESETB_GPIO, (DS101_GPIO_IN|IRQT_FALLING)); -+ gpio_line_config(DS101_USBCOPYB_GPIO, (DS101_GPIO_IN|IRQT_FALLING)); -+ set_irq_type(DS101_USBCOPYB_IRQ, IRQT_FALLING); -+ set_irq_type(DS101_POWERB_IRQ, IRQT_FALLING); -+ set_irq_type(DS101_RESETB_IRQ, IRQT_FALLING); -+ if (request_irq(DS101_USBCOPYB_IRQ, &ds101_usbcopy_handler, SA_INTERRUPT, -+ "DS101 USBCopy button", NULL) < 0) -+ { -+ printk(KERN_DEBUG "Could not get USBCopy button IRQ (%d)\n", -+ DS101_USBCOPYB_IRQ); -+ -+ return -EIO; -+ } -+ -+ if (request_irq(DS101_POWERB_IRQ, &ds101_power_handler, SA_INTERRUPT, -+ "DS101 Powerbutton", NULL) < 0) -+ { -+ printk(KERN_DEBUG "Could not get powerbutton IRQ (%d)\n", -+ DS101_POWERB_IRQ); -+ return -EIO; -+ } -+ -+ if (request_irq(DS101_RESETB_IRQ, &ds101_reset_handler, SA_INTERRUPT, -+ "DS101 Resetbutton", NULL) < 0) -+ { -+ printk(KERN_DEBUG "Could not get resetbutton IRQ (%d)\n", -+ DS101_RESETB_IRQ); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static void __exit ds101_buttons_exit(void) -+{ -+ if (!(machine_is_ds101())) -+ return; -+ -+ disable_irq(DS101_USBCOPYB_IRQ); -+ disable_irq(DS101_POWERB_IRQ); -+ disable_irq(DS101_RESETB_IRQ); -+ free_irq(DS101_USBCOPYB_IRQ, NULL); -+ free_irq(DS101_POWERB_IRQ, NULL); -+ free_irq(DS101_RESETB_IRQ, NULL); -+} -+ -+module_init(ds101_buttons_init); -+module_exit(ds101_buttons_exit); -+ -+MODULE_AUTHOR("OEyvind Repvik <nail@nslu2-linux.org>"); -+MODULE_DESCRIPTION("DS101 Button driver"); -+MODULE_LICENSE("GPL"); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-doc.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-doc.patch deleted file mode 100644 index 470c03ab56..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-doc.patch +++ /dev/null @@ -1,43 +0,0 @@ -Index: linux-2.6.15/include/linux/mtd/doc2000.h -=================================================================== ---- linux-2.6.15.orig/include/linux/mtd/doc2000.h 2006-02-24 11:46:50.000000000 +0100 -+++ linux-2.6.15/include/linux/mtd/doc2000.h 2006-02-24 12:14:18.000000000 +0100 -@@ -73,14 +73,29 @@ - #define DoC_Mplus_Toggle 0x1046 - #define DoC_Mplus_DownloadStatus 0x1074 - #define DoC_Mplus_CtrlConfirm 0x1076 -+#ifdef CONFIG_MACH_DS101 -+#define DoC_Mplus_Power 0x1ffe -+#else - #define DoC_Mplus_Power 0x1fff -+#endif - - /* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. - * On PPC, it's mmap'd and 16-bit wide. -+ * On DS101 (an ARM device), some tricks are needed - * Others use readb/writeb - */ --#if defined(__arm__) -+#ifdef CONFIG_MACH_DS101 -+#ifndef __ARMEB__ -+#define ReadDOC_(adr, reg) readw((unsigned long)(adr + reg) ^ 0x02) -+#define WriteDOC_(d, adr, reg) writew(d, (unsigned long)(adr + reg) ^ 0x02) -+#define DOC_IOREMAP_LEN 0x4000 -+#else -+#define ReadDOC_(adr, reg) swab16(readw((void __iomem *)(adr) + (reg))) -+#define WriteDOC_(d, adr, reg) writew(swab16(d), (void __iomem *)(adr) + (reg)) -+#define DOC_IOREMAP_LEN 0x4000 -+#endif -+#elif defined(__arm__) - #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) - #define WriteDOC_(d, adr, reg) do{ *(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)) = (__u32)d; wmb();} while(0) - #define DOC_IOREMAP_LEN 0x8000 -@@ -92,7 +107,6 @@ - #define ReadDOC_(adr, reg) readb((void __iomem *)(adr) + (reg)) - #define WriteDOC_(d, adr, reg) writeb(d, (void __iomem *)(adr) + (reg)) - #define DOC_IOREMAP_LEN 0x2000 -- - #endif - - #if defined(__i386__) || defined(__x86_64__) diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-includes.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-includes.patch deleted file mode 100644 index 3f94fab289..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-includes.patch +++ /dev/null @@ -1,120 +0,0 @@ - include/asm-arm/arch-ixp4xx/ds101.h | 87 +++++++++++++++++++++++++++++++++ - include/asm-arm/arch-ixp4xx/hardware.h | 1 - include/asm-arm/arch-ixp4xx/irqs.h | 7 ++ - 3 files changed, 95 insertions(+) - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/ds101.h 2006-02-23 18:09:24.000000000 +0100 -@@ -0,0 +1,87 @@ -+/* -+ * DS101 platform specific definitions -+ * -+ * Author: Øyvind Repvik <nail@nslu2-linux.org> -+ * -+ * based on ixdp425.h: -+ * Copyright 2004 (c) MontaVista, Software, Inc. -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#ifndef __ASM_ARCH_HARDWARE_H__ -+#error "Do not include this directly, instead #include <asm/hardware.h>" -+#endif -+ -+#define DS101_SCL_PIN DS101_GPIO0 -+#define DS101_SDA_PIN DS101_GPIO1 -+#define DS101_GPIO_BUZZ DS101_GPIO2 -+#define DS101_POWER_LED DS101_GPIO3 -+#define DS101_USBCOPYB_GPIO DS101_GPIO4 -+#define DS101_USBCOPY_SOLID_LED DS101_GPIO4 /* The led and button share GPIO */ -+#define DS101_USBCOPY_BLINK_LED DS101_GPIO5 -+/* GPIO6 is unknown */ -+#define DS101_POWEROFF_GPIO DS101_GPIO7 -+#define DS101_POWERB_GPIO DS101_GPIO8 -+#define DS101_PCI_INTC_PIN DS101_GPIO9 -+#define DS101_PCI_INTB_PIN DS101_GPIO10 -+#define DS101_PCI_INTA_PIN DS101_GPIO11 -+#define DS101_RESETB_GPIO DS101_GPIO12 -+#define DS101_STATUSOK_LED DS101_GPIO14 -+#define DS101_STATUSBAD_LED DS101_GPIO15 -+ -+#define DS101_PCI_MAX_DEV 2 -+#define DS101_PCI_IRQ_LINES 3 -+ -+#define DS101_POWERB_IRQ IRQ_IXP4XX_GPIO8 -+#define DS101_RESETB_IRQ IRQ_IXP4XX_GPIO12 -+#define DS101_USBCOPYB_IRQ IRQ_IXP4XX_GPIO4 -+ -+#define DS101_GPIO_IN IXP4XX_GPIO_IN -+#define DS101_GPIO_OUT IXP4XX_GPIO_OUT -+#define DS101_GPIO_HIGH 1 -+#define DS101_GPIO_LOW 0 -+ -+#define DS101_GPIO_CLK0_ENABLE 0x100 -+#define DS101_GPIO_CLK1_ENABLE 0x1000000 -+/* GPIO */ -+ -+#define DS101_GPIO0 0 -+#define DS101_GPIO1 1 -+#define DS101_GPIO2 2 -+#define DS101_GPIO3 3 -+#define DS101_GPIO4 4 -+#define DS101_GPIO5 5 -+#define DS101_GPIO6 6 -+#define DS101_GPIO7 7 -+#define DS101_GPIO8 8 -+#define DS101_GPIO9 9 -+#define DS101_GPIO10 10 -+#define DS101_GPIO11 11 -+#define DS101_GPIO12 12 -+#define DS101_GPIO13 13 -+#define DS101_GPIO14 14 -+#define DS101_GPIO15 15 -+ -+/* Stuff needed to setup the IXP expansion -+ * bus on the DS101 -+ */ -+ -+#define DS101_EXP_RECOVERY_T(x) (((x) & 15) << 16) -+#define DS101_EXP_HOLD_T(x) (((x) & 3) << 20) -+#define DS101_EXP_STROBE_T(x) (((x) & 15) << 22) -+#define DS101_EXP_SETUP_T(x) (((x) & 3) << 26) -+#define DS101_EXP_ADDR_T(x) (((x) & 3) << 28) -+ -+#define DS101_EXP_SZ_16M (15 << 10) -+#define DS101_EXP_WR_EN (1 << 1) -+#define DS101_EXP_BYTE_RD16 (1 << 6) -+#define DS101_EXP_CS_EN (1 << 31) -+ -+#define DS101_EXP_CS0_INIT (DS101_EXP_ADDR_T(1) | \ -+ DS101_EXP_SETUP_T(1) | DS101_EXP_STROBE_T(1) | \ -+ DS101_EXP_HOLD_T(1) | DS101_EXP_RECOVERY_T(1)| \ -+ DS101_EXP_SZ_16M | DS101_EXP_WR_EN | \ -+ DS101_EXP_BYTE_RD16 | DS101_EXP_CS_EN) ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/hardware.h 2006-02-23 18:09:14.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/hardware.h 2006-02-23 18:09:48.000000000 +0100 -@@ -47,5 +47,6 @@ extern unsigned int processor_id; - #include "nslu2.h" - #include "nas100d.h" - #include "dsmg600.h" -+#include "ds101.h" - - #endif /* _ASM_ARCH_HARDWARE_H */ ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/irqs.h 2006-02-23 18:09:14.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/irqs.h 2006-02-23 18:09:24.000000000 +0100 -@@ -108,6 +108,13 @@ - #define IRQ_NAS100D_PCI_INTC IRQ_IXP4XX_GPIO9 - #define IRQ_NAS100D_PCI_INTD IRQ_IXP4XX_GPIO8 - #define IRQ_NAS100D_PCI_INTE IRQ_IXP4XX_GPIO7 -+/* -+ * DS101 board IRQs -+ */ -+ -+#define IRQ_DS101_PCI_INTA IRQ_IXP4XX_GPIO11 -+#define IRQ_DS101_PCI_INTB IRQ_IXP4XX_GPIO10 -+#define IRQ_DS101_PCI_INTC IRQ_IXP4XX_GPIO9 - - /* - * D-Link DSM-G600 board IRQs diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-pci.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-pci.patch deleted file mode 100644 index 48765e3017..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-pci.patch +++ /dev/null @@ -1,72 +0,0 @@ - arch/arm/mach-ixp4xx/ds101-pci.c | 66 +++++++++++++++++++++++++++++++++++++++ - 1 file changed, 66 insertions(+) - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/ds101-pci.c 2006-02-21 02:02:34.000000000 +0100 -@@ -0,0 +1,66 @@ -+/* -+ * DS101 board-level PCI initialization -+ * -+ * based on ixdp425-pci.c: -+ * Copyright (C) 2002 Intel Corporation. -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Maintainer: http://www.nslu2-linux.org/ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+ -+#include <asm/mach/pci.h> -+#include <asm/mach-types.h> -+ -+void __init ds101_pci_preinit(void) -+{ -+ set_irq_type(IRQ_DS101_PCI_INTA, IRQT_LOW); -+ set_irq_type(IRQ_DS101_PCI_INTB, IRQT_LOW); -+ set_irq_type(IRQ_DS101_PCI_INTC, IRQT_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init ds101_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ static int pci_irq_table[DS101_PCI_MAX_DEV][DS101_PCI_IRQ_LINES] = -+ { -+ { IRQ_DS101_PCI_INTA, -1, -1 }, -+ { IRQ_DS101_PCI_INTB, IRQ_DS101_PCI_INTB, IRQ_DS101_PCI_INTC }, -+ }; -+ -+ int irq = -1; -+ -+ if (slot >= 1 && slot <= DS101_PCI_MAX_DEV && -+ pin >= 1 && pin <= DS101_PCI_IRQ_LINES) -+ irq = pci_irq_table[slot-1][pin-1]; -+ -+ return irq; -+} -+ -+struct hw_pci __initdata ds101_pci = { -+ .nr_controllers = 1, -+ .preinit = ds101_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = ds101_map_irq, -+}; -+ -+int __init ds101_pci_init(void) -+{ -+ if (machine_is_ds101()) -+ pci_common_init(&ds101_pci); -+ -+ return 0; -+} -+ -+subsys_initcall(ds101_pci_init); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-setup.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-setup.patch deleted file mode 100644 index 5c922d2934..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101-setup.patch +++ /dev/null @@ -1,290 +0,0 @@ -Board setup code for the Synology DS101 platform - -Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> -Signed-off-by: Rod Whitby <rod@whitby.id.au> -Signed-off-by: OEyvind Repvik <oyvind@repvik.org> - - arch/arm/mach-ixp4xx/Kconfig | 8 + - arch/arm/mach-ixp4xx/Makefile | 2 - arch/arm/mach-ixp4xx/ds101-setup.c | 245 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 254 insertions(+), 1 deletion(-) - -Index: linux-2.6.15/arch/arm/mach-ixp4xx/ds101-setup.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/ds101-setup.c 2006-02-24 12:37:01.000000000 +0100 -@@ -0,0 +1,245 @@ -+/* -+ * Synology DS101 board setup -+ * -+ * based ixdp425-setup.c: -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * Author: Rod Whitby <rod@whitby.id.au> -+ * Author: OEyvind Repvik <oyvind@repvik.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/serial.h> -+#include <linux/serial_8250.h> -+#include <linux/leds.h> -+#include <linux/pci.h> -+ -+#include <asm/setup.h> -+#include <asm/memory.h> -+#include <asm/mach-types.h> -+#include <asm/mach/arch.h> -+#include <asm/mach/flash.h> -+ -+#ifdef CONFIG_MACLIST -+#include <net/maclist.h> -+#endif -+ -+#ifdef CONFIG_LEDS_CLASS -+static struct resource ds101_led_resources[] = { -+ { -+ .name = "power", -+ .start = DS101_POWER_LED, -+ .end = DS101_POWER_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "usbcopy-solid", -+ .start = DS101_USBCOPY_SOLID_LED, -+ .end = DS101_USBCOPY_SOLID_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "usbcopy-blink", -+ .start = DS101_USBCOPY_BLINK_LED, -+ .end = DS101_USBCOPY_BLINK_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "status-ready", -+ .start = DS101_STATUSOK_LED, -+ .end = DS101_STATUSOK_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "status-error", -+ .start = DS101_STATUSBAD_LED, -+ .start = DS101_STATUSBAD_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ } -+}; -+ -+ -+static struct platform_device ds101_leds = { -+ .name = "IXP4XX-GPIO-LED", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(ds101_led_resources), -+ .resource = ds101_led_resources, -+}; -+#endif -+ -+static struct ixp4xx_i2c_pins ds101_i2c_gpio_pins = { -+ .sda_pin = DS101_SDA_PIN, -+ .scl_pin = DS101_SCL_PIN, -+}; -+ -+static struct platform_device ds101_i2c_controller = { -+ .name = "IXP4XX-I2C", -+ .id = 0, -+ .dev.platform_data = &ds101_i2c_gpio_pins, -+ .num_resources = 0, -+}; -+ -+static struct platform_device ds101_beeper = { -+ .name = "ixp4xx-beeper", -+ .id = DS101_GPIO_BUZZ, -+ .num_resources = 0, -+}; -+ -+static struct resource ds101_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct plat_serial8250_port ds101_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { } -+}; -+ -+static struct platform_device ds101_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = ds101_uart_data, -+ .num_resources = 2, -+ .resource = ds101_uart_resources, -+}; -+ -+static struct platform_device *ds101_devices[] __initdata = { -+ &ds101_i2c_controller, -+ &ds101_beeper, -+}; -+ -+static void ds101_power_off(void) -+{ -+ /* Simple, but effective */ -+ gpio_line_set(DS101_POWEROFF_GPIO, IXP4XX_GPIO_LOW); -+} -+ -+static void ds101_gpio_setup(void) -+{ -+ /* Set up buzzer */ -+ gpio_line_config(DS101_GPIO_BUZZ, DS101_GPIO_OUT); -+ gpio_line_set(DS101_GPIO_BUZZ, DS101_GPIO_LOW); -+ -+ /* Set up power led */ -+ gpio_line_config(DS101_POWER_LED, DS101_GPIO_OUT); -+ gpio_line_set(DS101_POWER_LED, DS101_GPIO_LOW); -+ -+ /* Poweroff */ -+ gpio_line_config(DS101_POWEROFF_GPIO, DS101_GPIO_OUT); -+ gpio_line_set(DS101_POWEROFF_GPIO, DS101_GPIO_HIGH); -+ -+ /* Status leds */ -+ (*IXP4XX_GPIO_GPCLKR) = ((*IXP4XX_GPIO_GPCLKR) & ~DS101_GPIO_CLK0_ENABLE); -+ (*IXP4XX_GPIO_GPCLKR) = ((*IXP4XX_GPIO_GPCLKR) & ~DS101_GPIO_CLK1_ENABLE); -+ gpio_line_config(DS101_STATUSOK_LED, DS101_GPIO_OUT); -+ gpio_line_config(DS101_STATUSBAD_LED, DS101_GPIO_OUT); -+ gpio_line_set(DS101_STATUSOK_LED, DS101_GPIO_HIGH); -+ gpio_line_set(DS101_STATUSBAD_LED, DS101_GPIO_LOW); -+}; -+ -+static void ds101_cs0_setup(void) -+{ -+ *IXP4XX_EXP_CS0 = DS101_EXP_CS0_INIT; -+}; -+ -+static void __init ds101_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ ds101_cs0_setup(); /* Needed for DoC support */ -+ ds101_gpio_setup(); -+ pm_power_off = ds101_power_off; -+ -+ platform_add_devices(ds101_devices, ARRAY_SIZE(ds101_devices)); -+ -+ /* This is only useful on a modified machine, but it is valuable -+ * to have it first in order to see debug messages, and so that -+ * it does *not* get removed if platform_add_devices fails! -+ */ -+ (void)platform_device_register(&ds101_uart); -+ -+#ifdef CONFIG_LEDS_CLASS -+ /* We don't care whether or not this works. */ -+ (void)platform_device_register(&ds101_leds); -+#endif -+} -+ -+/* -+ * DS101 bootstrap may pass in parameters, but we zap the mem -+ * settings to be safe (DS101 always has 64MByte at 0, DS101J has -+ * 32MB). The passed in command line can override this default, we -+ * prepend to the config'ed default. -+ * -+ * NOTE: the startup sequence is: -+ * 1) Call the machine fixup -+ * 2) Parse the ATAG list, the ATAG_CMDLINE is copied in -+ * to default_command_line which is the value of *from -+ * 3) Parse the command line in *from (*not* -+ * default_command_line unless they are the same!) -+ * -+ * Setting mi->nr_banks causes (2) to 'squash' (set to ATAG_NONE) -+ * any ATAG_MEM tags, but mem= command line options cause nr_banks -+ * to be reset to 0 (on the first mem=) -+ */ -+ -+static char ds101_command_line[] __initdata = -+ "root=/dev/sda2 rootfstype=ext3 init=/sbin/init " -+ "rtc-rs5c372.probe=0,0x32 " -+ CONFIG_CMDLINE; -+ -+static void __init ds101_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+{ -+ /* The DS101 has one bank of 64MByte memory. -+ * NOTE: setting nr_banks != 0 causes kernel/setup.c to remove -+ * the mem tags from the tag list. We need do nothing here! -+ */ -+ mi->nr_banks=1; -+ mi->bank[0].start = 0; -+ mi->bank[0].size = (64*1024*1024); -+ mi->bank[0].node = PHYS_TO_NID(0); -+ /* A command line in the ATAG list will override this one, -+ * as is intended. -+ */ -+ strlcpy(*cmdline, ds101_command_line, COMMAND_LINE_SIZE); -+} -+ -+MACHINE_START(DS101, "Synology DiskStation DS101") -+ /* Maintainer: www.nslu2-linux.org */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, -+ .boot_params = 0x00000100, -+ .fixup = ds101_fixup, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .init_machine = ds101_init, -+MACHINE_END -Index: linux-2.6.15/arch/arm/mach-ixp4xx/Kconfig -=================================================================== ---- linux-2.6.15.orig/arch/arm/mach-ixp4xx/Kconfig 2006-02-24 11:44:49.000000000 +0100 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/Kconfig 2006-02-24 11:44:49.000000000 +0100 -@@ -94,6 +94,14 @@ - DSM-G600 device. For more information on this platform, - see http://www.nslu2-linux.org/ - -+config MACH_DS101 -+ bool -+ prompt "DS101" -+ help -+ Say 'Y' here if you want your kernel to support Synology's -+ DiskStation DS101(j) device. For more information on this -+ platform see http://www.nslu2-linux.org/wiki/DS101/HomePage -+ - # - # Avila and IXDP share the same source for now. Will change in future - # -Index: linux-2.6.15/arch/arm/mach-ixp4xx/Makefile -=================================================================== ---- linux-2.6.15.orig/arch/arm/mach-ixp4xx/Makefile 2006-02-24 11:44:48.000000000 +0100 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/Makefile 2006-02-24 11:44:49.000000000 +0100 -@@ -11,4 +11,4 @@ - obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o - obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o - obj-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o dsmg600-setup.o -- -+obj-$(CONFIG_MACH_DS101) += ds101-pci.o ds101-setup.o ds101-buttons.o diff --git a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101.patch b/packages/linux/ixp4xx-kernel/2.6.16/97-ds101.patch deleted file mode 100644 index 77df5ace86..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/97-ds101.patch +++ /dev/null @@ -1,457 +0,0 @@ - arch/arm/mach-ixp4xx/Kconfig | 8 + - arch/arm/mach-ixp4xx/Makefile | 2 - arch/arm/mach-ixp4xx/ds101-pci.c | 66 +++++++++ - arch/arm/mach-ixp4xx/ds101-setup.c | 234 +++++++++++++++++++++++++++++++++ - include/asm-arm/arch-ixp4xx/ds101.h | 88 ++++++++++++ - include/asm-arm/arch-ixp4xx/hardware.h | 1 - include/asm-arm/arch-ixp4xx/irqs.h | 8 + - 7 files changed, 406 insertions(+), 1 deletion(-) - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/ds101.h 2006-03-08 08:41:31.000000000 +0100 -@@ -0,0 +1,88 @@ -+/* -+ * DS101 platform specific definitions -+ * -+ * Author: Øyvind Repvik <nail@nslu2-linux.org> -+ * -+ * based on ixdp425.h: -+ * Copyright 2004 (c) MontaVista, Software, Inc. -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#ifndef __ASM_ARCH_HARDWARE_H__ -+#error "Do not include this directly, instead #include <asm/hardware.h>" -+#endif -+ -+#define DS101_SCL_PIN DS101_GPIO0 -+#define DS101_SDA_PIN DS101_GPIO1 -+#define DS101_GPIO_BUZZ DS101_GPIO2 -+#define DS101_POWER_LED DS101_GPIO3 -+#define DS101_USBCOPYB_GPIO DS101_GPIO4 /* shared */ -+#define DS101_USBCOPY_SOLID_LED DS101_GPIO4 /* shared */ -+#define DS101_USBCOPY_BLINK_LED DS101_GPIO5 -+/* GPIO6 is unknown */ -+#define DS101_POWEROFF_GPIO DS101_GPIO7 -+#define DS101_POWERB_GPIO DS101_GPIO8 -+/*#define DS101_PCI_INTC_PIN DS101_GPIO9 -+#define DS101_PCI_INTB_PIN DS101_GPIO10 -+#define DS101_PCI_INTA_PIN DS101_GPIO11 -+*/ -+#define DS101_RESETB_GPIO DS101_GPIO12 -+#define DS101_STATUSOK_LED DS101_GPIO14 -+#define DS101_STATUSBAD_LED DS101_GPIO15 -+ -+#define DS101_PCI_MAX_DEV 2 -+#define DS101_PCI_IRQ_LINES 3 -+ -+#define DS101_POWERB_IRQ IRQ_IXP4XX_GPIO8 -+#define DS101_RESETB_IRQ IRQ_IXP4XX_GPIO12 -+#define DS101_USBCOPYB_IRQ IRQ_IXP4XX_GPIO4 -+ -+/* XXX use IXP4XX_GPIO_XX directly */ -+#define DS101_GPIO_IN IXP4XX_GPIO_IN -+#define DS101_GPIO_OUT IXP4XX_GPIO_OUT -+#define DS101_GPIO_HIGH 1 -+#define DS101_GPIO_LOW 0 -+ -+/* GPIO */ -+ -+#define DS101_GPIO0 0 -+#define DS101_GPIO1 1 -+#define DS101_GPIO2 2 -+#define DS101_GPIO3 3 -+#define DS101_GPIO4 4 -+#define DS101_GPIO5 5 -+#define DS101_GPIO6 6 -+#define DS101_GPIO7 7 -+#define DS101_GPIO8 8 -+#define DS101_GPIO9 9 -+#define DS101_GPIO10 10 -+#define DS101_GPIO11 11 -+#define DS101_GPIO12 12 -+#define DS101_GPIO13 13 -+#define DS101_GPIO14 14 -+#define DS101_GPIO15 15 -+ -+/* Stuff needed to setup the IXP expansion -+ * bus on the DS101 -+ */ -+ -+#define DS101_EXP_RECOVERY_T(x) (((x) & 15) << 16) -+#define DS101_EXP_HOLD_T(x) (((x) & 3) << 20) -+#define DS101_EXP_STROBE_T(x) (((x) & 15) << 22) -+#define DS101_EXP_SETUP_T(x) (((x) & 3) << 26) -+#define DS101_EXP_ADDR_T(x) (((x) & 3) << 28) -+ -+#define DS101_EXP_SZ_16M (15 << 10) -+#define DS101_EXP_WR_EN (1 << 1) -+#define DS101_EXP_BYTE_RD16 (1 << 6) -+#define DS101_EXP_CS_EN (1 << 31) -+ -+/* XXX nope. use the _EXP_ macros in the -setup.c */ -+#define DS101_EXP_CS0_INIT (DS101_EXP_ADDR_T(1) | \ -+ DS101_EXP_SETUP_T(1) | DS101_EXP_STROBE_T(1) | \ -+ DS101_EXP_HOLD_T(1) | DS101_EXP_RECOVERY_T(1)| \ -+ DS101_EXP_SZ_16M | DS101_EXP_WR_EN | \ -+ DS101_EXP_BYTE_RD16 | DS101_EXP_CS_EN) ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/hardware.h 2006-03-08 08:41:02.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/hardware.h 2006-03-08 08:41:31.000000000 +0100 -@@ -47,5 +47,6 @@ extern unsigned int processor_id; - #include "nslu2.h" - #include "nas100d.h" - #include "dsmg600.h" -+#include "ds101.h" - - #endif /* _ASM_ARCH_HARDWARE_H */ ---- linux-ixp4xx.orig/include/asm-arm/arch-ixp4xx/irqs.h 2006-03-08 08:41:02.000000000 +0100 -+++ linux-ixp4xx/include/asm-arm/arch-ixp4xx/irqs.h 2006-03-08 08:41:31.000000000 +0100 -@@ -110,6 +110,14 @@ - #define IRQ_NAS100D_PCI_INTE IRQ_IXP4XX_GPIO7 - - /* -+ * Synology DS101 board IRQs -+ */ -+ -+#define IRQ_DS101_PCI_INTA IRQ_IXP4XX_GPIO11 -+#define IRQ_DS101_PCI_INTB IRQ_IXP4XX_GPIO10 -+#define IRQ_DS101_PCI_INTC IRQ_IXP4XX_GPIO9 -+ -+/* - * D-Link DSM-G600 board IRQs - */ - #define IRQ_DSMG600_PCI_INTA IRQ_IXP4XX_GPIO11 ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/ds101-pci.c 2006-03-08 08:41:31.000000000 +0100 -@@ -0,0 +1,66 @@ -+/* -+ * DS101 board-level PCI initialization -+ * -+ * based on ixdp425-pci.c: -+ * Copyright (C) 2002 Intel Corporation. -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Maintainer: http://www.nslu2-linux.org/ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+ -+#include <asm/mach/pci.h> -+#include <asm/mach-types.h> -+ -+void __init ds101_pci_preinit(void) -+{ -+ set_irq_type(IRQ_DS101_PCI_INTA, IRQT_LOW); -+ set_irq_type(IRQ_DS101_PCI_INTB, IRQT_LOW); -+ set_irq_type(IRQ_DS101_PCI_INTC, IRQT_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init ds101_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ static int pci_irq_table[DS101_PCI_MAX_DEV][DS101_PCI_IRQ_LINES] = -+ { -+ { IRQ_DS101_PCI_INTA, -1, -1 }, -+ { IRQ_DS101_PCI_INTB, IRQ_DS101_PCI_INTB, IRQ_DS101_PCI_INTC }, -+ }; -+ -+ int irq = -1; -+ -+ if (slot >= 1 && slot <= DS101_PCI_MAX_DEV && -+ pin >= 1 && pin <= DS101_PCI_IRQ_LINES) -+ irq = pci_irq_table[slot-1][pin-1]; -+ -+ return irq; -+} -+ -+struct hw_pci __initdata ds101_pci = { -+ .nr_controllers = 1, -+ .preinit = ds101_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = ds101_map_irq, -+}; -+ -+int __init ds101_pci_init(void) -+{ -+ if (machine_is_ds101()) -+ pci_common_init(&ds101_pci); -+ -+ return 0; -+} -+ -+subsys_initcall(ds101_pci_init); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/ds101-setup.c 2006-03-08 08:41:31.000000000 +0100 -@@ -0,0 +1,234 @@ -+/* -+ * Synology DS101 board setup -+ * -+ * based ixdp425-setup.c: -+ * Copyright (C) 2003-2004 MontaVista Software, Inc. -+ * -+ * Author: Alessandro Zummo <a.zummo@towertech.it> -+ * Author: Rod Whitby <rod@whitby.id.au> -+ * Author: OEyvind Repvik <oyvind@repvik.org> -+ * Maintainers: http://www.nslu2-linux.org/ -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/serial.h> -+#include <linux/serial_8250.h> -+#include <linux/leds.h> -+#include <linux/pci.h> -+ -+#include <asm/setup.h> -+#include <asm/memory.h> -+#include <asm/mach-types.h> -+#include <asm/mach/arch.h> -+#include <asm/mach/flash.h> -+ -+#ifdef CONFIG_LEDS_CLASS -+static struct resource ds101_led_resources[] = { -+ { -+ .name = "power", -+ .start = DS101_POWER_LED, -+ .end = DS101_POWER_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "usbcopy-solid", -+ .start = DS101_USBCOPY_SOLID_LED, -+ .end = DS101_USBCOPY_SOLID_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "usbcopy-blink", -+ .start = DS101_USBCOPY_BLINK_LED, -+ .end = DS101_USBCOPY_BLINK_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "status-ready", -+ .start = DS101_STATUSOK_LED, -+ .end = DS101_STATUSOK_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ }, -+ { -+ .name = "status-error", -+ .start = DS101_STATUSBAD_LED, -+ .start = DS101_STATUSBAD_LED, -+ .flags = IXP4XX_GPIO_LOW, -+ } -+}; -+ -+ -+static struct platform_device ds101_leds = { -+ .name = "IXP4XX-GPIO-LED", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(ds101_led_resources), -+ .resource = ds101_led_resources, -+}; -+#endif -+ -+static struct ixp4xx_i2c_pins ds101_i2c_gpio_pins = { -+ .sda_pin = DS101_SDA_PIN, -+ .scl_pin = DS101_SCL_PIN, -+}; -+ -+static struct platform_device ds101_i2c_controller = { -+ .name = "IXP4XX-I2C", -+ .id = 0, -+ .dev.platform_data = &ds101_i2c_gpio_pins, -+ .num_resources = 0, -+}; -+ -+static struct platform_device ds101_beeper = { -+ .name = "ixp4xx-beeper", -+ .id = DS101_GPIO_BUZZ, -+ .num_resources = 0, -+}; -+ -+static struct resource ds101_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct plat_serial8250_port ds101_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { } -+}; -+ -+static struct platform_device ds101_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = ds101_uart_data, -+ .num_resources = 2, -+ .resource = ds101_uart_resources, -+}; -+ -+static struct platform_device *ds101_devices[] __initdata = { -+ &ds101_i2c_controller, -+ &ds101_beeper, -+}; -+ -+static void ds101_power_off(void) -+{ -+ /* Simple, but effective */ -+ gpio_line_set(DS101_POWEROFF_GPIO, IXP4XX_GPIO_LOW); -+} -+ -+static void ds101_gpio_setup(void) -+{ -+ /* Set up buzzer */ -+ gpio_line_config(DS101_GPIO_BUZZ, DS101_GPIO_OUT); -+ gpio_line_set(DS101_GPIO_BUZZ, DS101_GPIO_LOW); -+ -+ /* Set up power led */ -+ gpio_line_config(DS101_POWER_LED, DS101_GPIO_OUT); -+ gpio_line_set(DS101_POWER_LED, DS101_GPIO_LOW); -+ -+ /* Poweroff */ -+ gpio_line_config(DS101_POWEROFF_GPIO, DS101_GPIO_OUT); -+ gpio_line_set(DS101_POWEROFF_GPIO, DS101_GPIO_HIGH); -+ -+ /* Status leds */ -+ *IXP4XX_GPIO_GPCLKR = 0; -+ -+ /* XXX can't the leds subsystem take care of those? */ -+ gpio_line_config(DS101_STATUSOK_LED, DS101_GPIO_OUT); -+ gpio_line_config(DS101_STATUSBAD_LED, DS101_GPIO_OUT); -+ gpio_line_set(DS101_STATUSOK_LED, DS101_GPIO_HIGH); -+ gpio_line_set(DS101_STATUSBAD_LED, DS101_GPIO_LOW); -+}; -+ -+static void ds101_cs0_setup(void) -+{ -+ /* XXX don't use macro */ -+ *IXP4XX_EXP_CS0 = DS101_EXP_CS0_INIT; -+}; -+ -+static void __init ds101_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ ds101_cs0_setup(); /* Needed for DoC support */ -+ ds101_gpio_setup(); -+ pm_power_off = ds101_power_off; -+ -+ platform_add_devices(ds101_devices, ARRAY_SIZE(ds101_devices)); -+ -+ /* This is only useful on a modified machine, but it is valuable -+ * to have it first in order to see debug messages, and so that -+ * it does *not* get removed if platform_add_devices fails! -+ */ -+ (void)platform_device_register(&ds101_uart); -+ -+#ifdef CONFIG_LEDS_CLASS -+ /* We don't care whether or not this works. */ -+ (void)platform_device_register(&ds101_leds); -+#endif -+} -+ -+/* -+ * DS101 bootstrap may pass in parameters, but we zap the mem -+ * settings to be safe (DS101 always has 64MByte at 0, DS101J has -+ * 32MB). The passed in command line can override this default, we -+ * prepend to the config'ed default. -+ * -+ * NOTE: the startup sequence is: -+ * 1) Call the machine fixup -+ * 2) Parse the ATAG list, the ATAG_CMDLINE is copied in -+ * to default_command_line which is the value of *from -+ * 3) Parse the command line in *from (*not* -+ * default_command_line unless they are the same!) -+ * -+ * Setting mi->nr_banks causes (2) to 'squash' (set to ATAG_NONE) -+ * any ATAG_MEM tags, but mem= command line options cause nr_banks -+ * to be reset to 0 (on the first mem=) -+ */ -+ -+static void __init ds101_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+{ -+ /* The DS101 has one bank of 64MByte memory. -+ * NOTE: setting nr_banks != 0 causes kernel/setup.c to remove -+ * the mem tags from the tag list. We need do nothing here! -+ */ -+ mi->nr_banks = 1; -+ mi->bank[0].start = 0; -+ mi->bank[0].size = (64*1024*1024); -+ mi->bank[0].node = PHYS_TO_NID(0); -+} -+ -+MACHINE_START(DS101, "Synology DiskStation DS101") -+ /* Maintainer: www.nslu2-linux.org */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC, -+ .boot_params = 0x00000100, -+ .fixup = ds101_fixup, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .init_machine = ds101_init, -+MACHINE_END ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/Kconfig 2006-03-08 08:41:02.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/Kconfig 2006-03-08 08:41:31.000000000 +0100 -@@ -93,6 +93,14 @@ config MACH_DSMG600 - DSM-G600 device. For more information on this platform, - see http://www.nslu2-linux.org/ - -+config MACH_DS101 -+ bool -+ prompt "Synology DS101" -+ help -+ Say 'Y' here if you want your kernel to support Synology's -+ DiskStation DS101(j) device. For more information on this -+ platform see http://www.nslu2-linux.org/wiki/DS101/HomePage -+ - # - # Avila and IXDP share the same source for now. Will change in future - # ---- linux-ixp4xx.orig/arch/arm/mach-ixp4xx/Makefile 2006-03-08 08:41:02.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-ixp4xx/Makefile 2006-03-08 08:41:31.000000000 +0100 -@@ -11,4 +11,4 @@ obj-$(CONFIG_MACH_GTWX5715) += gtwx5715- - obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o - obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o - obj-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o dsmg600-setup.o -- -+obj-$(CONFIG_MACH_DS101) += ds101-pci.o ds101-setup.o diff --git a/packages/linux/ixp4xx-kernel/2.6.16/copypage-xscale.patch b/packages/linux/ixp4xx-kernel/2.6.16/copypage-xscale.patch deleted file mode 100644 index b73d219708..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/copypage-xscale.patch +++ /dev/null @@ -1,21 +0,0 @@ -*** linux-2.6.16/arch/arm/mm/copypage-xscale.c- Mon Mar 27 19:10:25 2006 ---- linux-2.6.16/arch/arm/mm/copypage-xscale.c Sun Mar 26 19:32:53 2006 -*************** -*** 15,20 **** ---- 15,21 ---- - */ - #include <linux/init.h> - #include <linux/mm.h> -+ #include <linux/module.h> - - #include <asm/page.h> - #include <asm/pgtable.h> -*************** -*** 129,131 **** ---- 130,135 ---- - .cpu_clear_user_page = xscale_mc_clear_user_page, - .cpu_copy_user_page = xscale_mc_copy_user_page, - }; -+ -+ EXPORT_SYMBOL(xscale_mc_clear_user_page); -+ EXPORT_SYMBOL(xscale_mc_copy_user_page); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/defconfig b/packages/linux/ixp4xx-kernel/2.6.16/defconfig deleted file mode 100644 index dda2e790b0..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/defconfig +++ /dev/null @@ -1,1771 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.16 -# Fri Apr 7 02:45:02 2006 -# -CONFIG_ARM=y -CONFIG_MMU=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_CALIBRATE_DELAY=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_UID16=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_EMBEDDED=y -# CONFIG_KALLSYMS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -CONFIG_SLAB=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set -CONFIG_OBSOLETE_INTERMODULE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y - -# -# Block layer -# - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -CONFIG_IOSCHED_DEADLINE=y -# CONFIG_IOSCHED_CFQ is not set -# CONFIG_DEFAULT_AS is not set -CONFIG_DEFAULT_DEADLINE=y -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="deadline" - -# -# System Type -# -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP3XX is not set -CONFIG_ARCH_IXP4XX=y -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_AT91RM9200 is not set -CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y - -# -# Intel IXP4xx Implementation Options -# - -# -# IXP4xx Platforms -# -CONFIG_MACH_NSLU2=y -CONFIG_ARCH_AVILA=y -CONFIG_MACH_LOFT=y -# CONFIG_ARCH_ADI_COYOTE is not set -CONFIG_ARCH_IXDP425=y -# CONFIG_MACH_IXDPG425 is not set -# CONFIG_MACH_IXDP465 is not set -CONFIG_ARCH_IXCDP1100=y -# CONFIG_ARCH_PRPMC1100 is not set -CONFIG_MACH_NAS100D=y -CONFIG_MACH_DSMG600=y -CONFIG_MACH_DS101=y -CONFIG_ARCH_IXDP4XX=y -# CONFIG_MACH_GTWX5715 is not set - -# -# IXP4xx Options -# -# CONFIG_IXP4XX_INDIRECT_PCI is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_XSCALE=y -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_TLB_V4WBI=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y -# CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_XSCALE_PMU=y -CONFIG_DMABOUNCE=y - -# -# Bus support -# -CONFIG_PCI=y -# CONFIG_PCI_LEGACY_PROC is not set - -# -# PCCARD (PCMCIA/CardBus) support -# -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_PREEMPT=y -# CONFIG_NO_IDLE_HZ is not set -# CONFIG_AEABI is not set -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4096 -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE=" noirqdebug console=ttyS0,115200n8" -# CONFIG_XIP_KERNEL is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set - -# -# Power management options -# -# CONFIG_PM is not set -# CONFIG_APM is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_NETDEBUG is not set -CONFIG_PACKET=m -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m -CONFIG_INET_TUNNEL=m -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_INET6_TUNNEL=m -CONFIG_IPV6_TUNNEL=m -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_BRIDGE_NETFILTER=y - -# -# Core Netfilter Configuration -# -# CONFIG_NETFILTER_NETLINK is not set -CONFIG_NETFILTER_XTABLES=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m - -# -# IP: Netfilter Configuration -# -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_CT_ACCT is not set -# CONFIG_IP_NF_CONNTRACK_MARK is not set -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -CONFIG_IP_NF_CT_PROTO_SCTP=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_NETBIOS_NS is not set -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -# CONFIG_IP_NF_PPTP is not set -CONFIG_IP_NF_QUEUE=m -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_MULTIPORT=m -CONFIG_IP_NF_MATCH_TOS=m -CONFIG_IP_NF_MATCH_RECENT=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_DSCP=m -CONFIG_IP_NF_MATCH_AH_ESP=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_MATCH_OWNER=m -CONFIG_IP_NF_MATCH_ADDRTYPE=m -CONFIG_IP_NF_MATCH_HASHLIMIT=m -CONFIG_IP_NF_MATCH_POLICY=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_LOG=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -CONFIG_IP_NF_NAT=m -CONFIG_IP_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_SNMP_BASIC=m -CONFIG_IP_NF_NAT_IRC=m -CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -CONFIG_IP_NF_NAT_AMANDA=m -CONFIG_IP_NF_MANGLE=m -CONFIG_IP_NF_TARGET_TOS=m -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_DSCP=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m - -# -# IPv6: Netfilter Configuration (EXPERIMENTAL) -# -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_RT=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_MULTIPORT=m -CONFIG_IP6_NF_MATCH_OWNER=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -CONFIG_IP6_NF_MATCH_AHESP=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_POLICY=m -CONFIG_IP6_NF_FILTER=m -CONFIG_IP6_NF_TARGET_LOG=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_RAW=m - -# -# Bridge: Netfilter Configuration -# -# CONFIG_BRIDGE_NF_EBTABLES is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -CONFIG_TIPC=m -# CONFIG_TIPC_ADVANCED is not set -# CONFIG_TIPC_DEBUG is not set -# CONFIG_ATM is not set -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -# CONFIG_DECNET is not set -CONFIG_LLC=m -# CONFIG_LLC2 is not set -CONFIG_IPX=m -# CONFIG_IPX_INTERN is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=y -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_IPDDP_DECAP=y -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -CONFIG_NET_CLS_ROUTE=y - -# -# Network testing -# -CONFIG_NET_PKTGEN=m -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -CONFIG_BT=m -CONFIG_BT_L2CAP=m -CONFIG_BT_SCO=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -# CONFIG_BT_HIDP is not set - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIUSB=m -CONFIG_BT_HCIUSB_SCO=y -# CONFIG_BT_HCIUART is not set -CONFIG_BT_HCIBCM203X=m -# CONFIG_BT_HCIBPA10X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIVHCI is not set -# CONFIG_IEEE80211 is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m - -# -# Connector - unified userspace <-> kernelspace linker -# -# CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set -# CONFIG_MTD_CMDLINE_PARTS is not set -# CONFIG_MTD_AFS_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -CONFIG_NFTL=y -CONFIG_NFTL_RW=y -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_NOSWAP is not set -CONFIG_MTD_CFI_BE_BYTE_SWAP=y -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set -CONFIG_MTD_MAP_BANK_WIDTH_2=y -# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_OTP is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -CONFIG_MTD_COMPLEX_MAPPINGS=y -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -CONFIG_MTD_IXP4XX=y -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_VERIFY_WRITE=y -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_NAND_DISKONCHIP=y -CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y -CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0x50000000 -# CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH is not set -# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set -# CONFIG_MTD_NAND_NANDSIM is not set - -# -# OneNAND Flash Device Drivers -# -# CONFIG_MTD_ONENAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=4 -CONFIG_BLK_DEV_RAM_SIZE=10240 -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CDROM_PKTCDVD=m -CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set -CONFIG_ATA_OVER_ETH=m - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=m -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=m -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI Transport Attributes -# -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_FC_ATTRS is not set -CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# -CONFIG_ISCSI_TCP=m -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set -# CONFIG_SCSI_SATA_SVW is not set -# CONFIG_SCSI_ATA_PIIX is not set -# CONFIG_SCSI_SATA_MV is not set -# CONFIG_SCSI_SATA_NV is not set -# CONFIG_SCSI_PDC_ADMA is not set -# CONFIG_SCSI_SATA_QSTOR is not set -# CONFIG_SCSI_SATA_PROMISE is not set -# CONFIG_SCSI_SATA_SX4 is not set -# CONFIG_SCSI_SATA_SIL is not set -# CONFIG_SCSI_SATA_SIL24 is not set -# CONFIG_SCSI_SATA_SIS is not set -# CONFIG_SCSI_SATA_ULI is not set -# CONFIG_SCSI_SATA_VIA is not set -# CONFIG_SCSI_SATA_VITESSE is not set -# CONFIG_SCSI_PATA_ALI is not set -# CONFIG_SCSI_PATA_AMD is not set -CONFIG_SCSI_PATA_ARTOP=y -# CONFIG_SCSI_PATA_ATIIXP is not set -# CONFIG_SCSI_PATA_CMD64X is not set -# CONFIG_SCSI_PATA_CS5520 is not set -# CONFIG_SCSI_PATA_CS5530 is not set -# CONFIG_SCSI_PATA_CYPRESS is not set -# CONFIG_SCSI_PATA_EFAR is not set -# CONFIG_SCSI_ATA_GENERIC is not set -# CONFIG_SCSI_PATA_HPT37X is not set -# CONFIG_SCSI_PATA_HPT3X2N is not set -# CONFIG_SCSI_PATA_HPT3X3 is not set -# CONFIG_SCSI_PATA_ISAPNP is not set -# CONFIG_SCSI_PATA_IT8172 is not set -# CONFIG_SCSI_PATA_IT821X is not set -# CONFIG_SCSI_PATA_LEGACY is not set -# CONFIG_SCSI_PATA_MPIIX is not set -# CONFIG_SCSI_PATA_NETCELL is not set -# CONFIG_SCSI_PATA_NS87410 is not set -# CONFIG_SCSI_PATA_OLDPIIX is not set -# CONFIG_SCSI_PATA_OPTI is not set -# CONFIG_SCSI_PATA_PDC_OLD is not set -# CONFIG_SCSI_PATA_QDI is not set -# CONFIG_SCSI_PATA_RADISYS is not set -# CONFIG_SCSI_PATA_RZ1000 is not set -# CONFIG_SCSI_PATA_SC1200 is not set -# CONFIG_SCSI_PATA_SERVERWORKS is not set -# CONFIG_SCSI_PATA_SIL680 is not set -# CONFIG_SCSI_PATA_SIS is not set -# CONFIG_SCSI_PATA_TRIFLEX is not set -# CONFIG_SCSI_PATA_VIA is not set -# CONFIG_SCSI_PATA_WINBOND is not set -CONFIG_SCSI_PATA_IXP4XX=y -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID5=m -CONFIG_MD_RAID6=m -CONFIG_MD_MULTIPATH=m -CONFIG_MD_FAULTY=m -CONFIG_BLK_DEV_DM=m -# CONFIG_DM_CRYPT is not set -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_ZERO is not set -# CONFIG_DM_MULTIPATH is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MACLIST=y -CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_SMC91X is not set -# CONFIG_DM9000 is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set - -# -# Wireless 802.11b ISA/PCI cards support -# -# CONFIG_HERMES is not set -# CONFIG_ATMEL is not set - -# -# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support -# -# CONFIG_PRISM54 is not set -# CONFIG_HOSTAP is not set -CONFIG_NET_WIRELESS=y - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_MPPE=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set -# CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set -CONFIG_NETCONSOLE=m -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -CONFIG_INPUT_IXP4XX_BEEPER=y -# CONFIG_INPUT_UINPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_SYNCLINK_GT is not set -CONFIG_N_HDLC=m -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=2 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set -CONFIG_IXP4XX_WATCHDOG=m - -# -# PCI-based Watchdog Cards -# -# CONFIG_PCIPCWATCHDOG is not set -# CONFIG_WDTPCI is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_CHARDEV=y - -# -# I2C Algorithms -# -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_IOP3XX is not set -CONFIG_I2C_IXP4XX=y -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set -# CONFIG_I2C_PCA_ISA is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -CONFIG_SENSORS_EEPROM=y -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -CONFIG_W1=m -# CONFIG_W1_MATROX is not set -CONFIG_W1_DS9490=m -CONFIG_W1_DS9490_BRIDGE=m -CONFIG_W1_THERM=m -CONFIG_W1_SMEM=m -CONFIG_W1_DS2433=m -CONFIG_W1_DS2433_CRC=y - -# -# Hardware Monitoring support -# -CONFIG_HWMON=m -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_FSCPOS is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_VT8231 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -CONFIG_SENSORS_AD741X=m -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# - -# -# LED devices -# -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_IXP4XX=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_CPU_ACTIVITY=y - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m - -# -# Video For Linux -# - -# -# Video Adapters -# -# CONFIG_VIDEO_ADV_DEBUG is not set -CONFIG_VIDEO_BT848=m -# CONFIG_VIDEO_SAA6588 is not set -CONFIG_VIDEO_CPIA=m -CONFIG_VIDEO_CPIA_USB=m -CONFIG_VIDEO_SAA5246A=m -CONFIG_VIDEO_SAA5249=m -CONFIG_TUNER_3036=m -CONFIG_VIDEO_STRADIS=m -CONFIG_VIDEO_ZORAN=m -CONFIG_VIDEO_ZORAN_BUZ=m -CONFIG_VIDEO_ZORAN_DC10=m -CONFIG_VIDEO_ZORAN_DC30=m -CONFIG_VIDEO_ZORAN_LML33=m -CONFIG_VIDEO_ZORAN_LML33R10=m -CONFIG_VIDEO_SAA7134=m -# CONFIG_VIDEO_SAA7134_ALSA is not set -CONFIG_VIDEO_MXB=m -CONFIG_VIDEO_DPC=m -CONFIG_VIDEO_HEXIUM_ORION=m -CONFIG_VIDEO_HEXIUM_GEMINI=m -CONFIG_VIDEO_CX88=m -CONFIG_VIDEO_CX88_ALSA=m -# CONFIG_VIDEO_EM28XX is not set -CONFIG_VIDEO_OVCAMCHIP=m -CONFIG_VIDEO_AUDIO_DECODER=m -CONFIG_VIDEO_DECODER=m - -# -# Radio Adapters -# -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_MAESTRO is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_VIDEO_VIDEOBUF=m -CONFIG_VIDEO_TUNER=m -CONFIG_VIDEO_BUF=m -CONFIG_VIDEO_BTCX=m -CONFIG_VIDEO_IR=m -CONFIG_VIDEO_TVEEPROM=m - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Sound -# -CONFIG_SOUND=m - -# -# Advanced Linux Sound Architecture -# -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -# CONFIG_SND_SEQUENCER is not set -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -# CONFIG_SND_VERBOSE_PRINTK is not set -# CONFIG_SND_DEBUG is not set - -# -# Generic devices -# -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set - -# -# PCI devices -# -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set - -# -# ALSA ARM devices -# - -# -# USB devices -# -CONFIG_SND_USB_AUDIO=m - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB=y -# CONFIG_USB_DEBUG is not set - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_OTG is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_SPLIT_ISO=y -CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_ISP116X_HCD is not set -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -CONFIG_USB_UHCI_HCD=y -# CONFIG_USB_SL811_HCD is not set - -# -# USB Device Class drivers -# -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# may also be needed; see USB_STORAGE Help for more information -# -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_USBAT is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_STORAGE_ONETOUCH is not set -# CONFIG_USB_LIBUSUAL is not set - -# -# USB Input Devices -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y - -# -# USB HID Boot Protocol drivers -# -CONFIG_USB_KBD=m -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -CONFIG_USB_YEALINK=m -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set - -# -# USB Imaging devices -# -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_W9968CF is not set -CONFIG_USB_PWC=m - -# -# USB Network Adapters -# -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_USBNET=m -CONFIG_USB_NET_AX8817X=m -CONFIG_USB_NET_CDCETHER=m -# CONFIG_USB_NET_GL620A is not set -CONFIG_USB_NET_NET1080=m -# CONFIG_USB_NET_PLUSB is not set -# CONFIG_USB_NET_RNDIS_HOST is not set -# CONFIG_USB_NET_CDC_SUBSET is not set -CONFIG_USB_NET_ZAURUS=m -# CONFIG_USB_ZD1201 is not set -# CONFIG_USB_MON is not set - -# -# USB port drivers -# - -# -# USB Serial Converter support -# -CONFIG_USB_SERIAL=m -CONFIG_USB_SERIAL_GENERIC=y -# CONFIG_USB_SERIAL_AIRPRIME is not set -# CONFIG_USB_SERIAL_ANYDATA is not set -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -# CONFIG_USB_SERIAL_CP2101 is not set -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -# CONFIG_USB_SERIAL_KEYSPAN is not set -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m -CONFIG_USB_SERIAL_PL2303=m -# CONFIG_USB_SERIAL_HP4X is not set -CONFIG_USB_SERIAL_SAFE=m -# CONFIG_USB_SERIAL_SAFE_PADDED is not set -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_EZUSB=y - -# -# USB Miscellaneous drivers -# -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_TEST is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# Real Time Clock -# -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" - -# -# RTC interfaces -# -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y - -# -# RTC drivers -# -CONFIG_RTC_DRV_X1205=y -CONFIG_RTC_DRV_DS1672=y -CONFIG_RTC_DRV_PCF8563=y -CONFIG_RTC_DRV_RS5C372=y -# CONFIG_RTC_DRV_TEST is not set - -# -# File systems -# -CONFIG_EXT2_FS=m -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_ZISOFS_FS=m -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="utf8" -CONFIG_NTFS_FS=m -# CONFIG_NTFS_DEBUG is not set -CONFIG_NTFS_RW=y - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_SUMMARY is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -# CONFIG_JFFS2_NATIVE_ENDIAN is not set -CONFIG_JFFS2_BIG_ENDIAN=y -# CONFIG_JFFS2_LITTLE_ENDIAN is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL is not set -CONFIG_NFS_V4=y -CONFIG_NFS_DIRECTIO=y -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V3_ACL is not set -CONFIG_NFSD_V4=y -CONFIG_NFSD_TCP=y -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_RPCSEC_GSS_SPKM3 is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -# CONFIG_CIFS_EXPERIMENTAL is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Native Language Support -# -CONFIG_NLS=m -CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_FRAME_POINTER=y -# CONFIG_DEBUG_USER is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -# CONFIG_CRYPTO_NULL is not set -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_DEFLATE=m -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# - -# -# Library routines -# -CONFIG_CRC_CCITT=m -CONFIG_CRC16=m -CONFIG_CRC32=y -CONFIG_LIBCRC32C=m -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_REED_SOLOMON=y -CONFIG_REED_SOLOMON_DEC16=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m diff --git a/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch b/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch deleted file mode 100644 index c0146b6fe4..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch +++ /dev/null @@ -1,1862 +0,0 @@ - -From: Richard Purdie <rpurdie@rpsys.net> - -Add the foundations of a new LEDs subsystem. This patch adds a class which -presents LED devices within sysfs and allows their brightness to be -controlled. - -Signed-off-by: Richard Purdie <rpurdie@rpsys.net> -Cc: Russell King <rmk@arm.linux.org.uk> -Cc: Greg KH <greg@kroah.com> -Signed-off-by: Andrew Morton <akpm@osdl.org> ---- - - arch/arm/Kconfig | 2 - arch/arm/mach-pxa/corgi.c | 9 + - arch/arm/mach-pxa/spitz.c | 9 + - arch/arm/mach-pxa/tosa.c | 9 + - drivers/Kconfig | 2 - drivers/Makefile | 1 - drivers/ide/ide-disk.c | 22 +++ - drivers/leds/Kconfig | 70 +++++++++++ - drivers/leds/Makefile | 15 ++ - drivers/leds/led-class.c | 174 +++++++++++++++++++++++++++++ - drivers/leds/led-core.c | 25 ++++ - drivers/leds/led-triggers.c | 239 ++++++++++++++++++++++++++++++++++++++++ - drivers/leds/leds-corgi.c | 121 ++++++++++++++++++++ - drivers/leds/leds-ixp4xx-gpio.c | 215 +++++++++++++++++++++++++++++++++++ - drivers/leds/leds-locomo.c | 95 +++++++++++++++ - drivers/leds/leds-spitz.c | 125 ++++++++++++++++++++ - drivers/leds/leds-tosa.c | 131 +++++++++++++++++++++ - drivers/leds/leds.h | 45 +++++++ - drivers/leds/ledtrig-timer.c | 174 +++++++++++++++++++++++++++++ - drivers/mtd/nand/nand_base.c | 26 ++++ - include/linux/leds.h | 105 +++++++++++++++++ - 21 files changed, 1610 insertions(+), 4 deletions(-) - ---- linux-ixp4xx.orig/arch/arm/Kconfig 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -807,6 +807,8 @@ source "drivers/misc/Kconfig" - - source "drivers/mfd/Kconfig" - -+source "drivers/leds/Kconfig" -+ - source "drivers/media/Kconfig" - - source "drivers/video/Kconfig" ---- linux-ixp4xx.orig/drivers/Kconfig 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -64,6 +64,8 @@ source "drivers/usb/Kconfig" - - source "drivers/mmc/Kconfig" - -+source "drivers/leds/Kconfig" -+ - source "drivers/infiniband/Kconfig" - - source "drivers/sn/Kconfig" ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,70 @@ -+ -+menu "LED devices" -+ -+config NEW_LEDS -+ bool "LED Support" -+ help -+ Say Y to enable Linux LED support. This is not related to standard -+ keyboard LEDs which are controlled via the input system. -+ -+config LEDS_CLASS -+ tristate "LED Class Support" -+ depends NEW_LEDS -+ help -+ This option enables the led sysfs class in /sys/class/leds. You'll -+ need this to do anything useful with LEDs. If unsure, say N. -+ -+config LEDS_TRIGGERS -+ bool "LED Trigger support" -+ depends NEW_LEDS -+ help -+ This option enables trigger support for the leds class. -+ These triggers allow kernel events to drive the LEDs and can -+ be configured via sysfs. If unsure, say Y. -+ -+config LEDS_CORGI -+ tristate "LED Support for the Sharp SL-C7x0 series" -+ depends LEDS_CLASS && PXA_SHARP_C7xx -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-C7x0 series (C700, C750, C760, C860). -+ -+config LEDS_LOCOMO -+ tristate "LED Support for Locomo device" -+ depends LEDS_CLASS && SHARP_LOCOMO -+ help -+ This option enables support for the LEDs on Sharp Locomo. -+ Zaurus models SL-5500 and SL-5600. -+ -+config LEDS_SPITZ -+ tristate "LED Support for the Sharp SL-Cxx00 series" -+ depends LEDS_CLASS && PXA_SHARP_Cxx00 -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-Cxx00 series (C1000, C3000, C3100). -+ -+config LEDS_IXP4XX -+ tristate "LED Support for GPIO connected LEDs on IXP4XX processors" -+ depends LEDS_CLASS && ARCH_IXP4XX -+ help -+ This option enables support for the LEDs connected to GPIO -+ outputs of the Intel IXP4XX processors. To be useful the -+ particular board must have LEDs and they must be connected -+ to the GPIO lines. If unsure, say Y. -+ -+config LEDS_TOSA -+ tristate "LED Support for the Sharp SL-6000 series" -+ depends LEDS_CLASS && PXA_SHARPSL -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-6000 series. -+ -+config LEDS_TRIGGER_TIMER -+ tristate "LED Timer Trigger" -+ depends LEDS_TRIGGERS -+ help -+ This allows LEDs to be controlled by a programmable timer -+ via sysfs. If unsure, say Y. -+ -+endmenu -+ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-class.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,174 @@ -+/* -+ * LED Class Core -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/err.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+static struct class *leds_class; -+ -+static ssize_t led_brightness_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ ssize_t ret = 0; -+ -+ /* no lock needed for this */ -+ sprintf(buf, "%u\n", led_cdev->brightness); -+ ret = strlen(buf) + 1; -+ -+ return ret; -+} -+ -+static ssize_t led_brightness_store(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ ssize_t ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ ret = after - buf; -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, state); -+ write_unlock(&led_cdev->lock); -+ } -+ -+ return ret; -+} -+ -+static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, -+ led_brightness_store); -+#ifdef CONFIG_LEDS_TRIGGERS -+static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); -+#endif -+ -+/** -+ * led_classdev_suspend - suspend an led_classdev. -+ * @led_cdev: the led_classdev to suspend. -+ */ -+void led_classdev_suspend(struct led_classdev *led_cdev) -+{ -+ write_lock(&led_cdev->lock); -+ led_cdev->flags |= LED_SUSPENDED; -+ led_cdev->brightness_set(led_cdev, 0); -+ write_unlock(&led_cdev->lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_suspend); -+ -+/** -+ * led_classdev_resume - resume an led_classdev. -+ * @led_cdev: the led_classdev to resume. -+ */ -+void led_classdev_resume(struct led_classdev *led_cdev) -+{ -+ write_lock(&led_cdev->lock); -+ led_cdev->flags &= ~LED_SUSPENDED; -+ led_cdev->brightness_set(led_cdev, led_cdev->brightness); -+ write_unlock(&led_cdev->lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_resume); -+ -+/** -+ * led_classdev_register - register a new object of led_classdev class. -+ * @dev: The device to register. -+ * @led_cdev: the led_classdev structure for this device. -+ */ -+int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) -+{ -+ led_cdev->class_dev = class_device_create(leds_class, NULL, 0, -+ parent, "%s", led_cdev->name); -+ if (unlikely(IS_ERR(led_cdev->class_dev))) -+ return PTR_ERR(led_cdev->class_dev); -+ -+ rwlock_init(&led_cdev->lock); -+ class_set_devdata(led_cdev->class_dev, led_cdev); -+ -+ /* register the attributes */ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_brightness); -+ -+ /* add to the list of leds */ -+ write_lock(&leds_list_lock); -+ list_add_tail(&led_cdev->node, &leds_list); -+ write_unlock(&leds_list_lock); -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+ rwlock_init(&led_cdev->trigger_lock); -+ -+ led_trigger_set_default(led_cdev); -+ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_trigger); -+#endif -+ -+ printk(KERN_INFO "Registered led device: %s\n", -+ led_cdev->class_dev->class_id); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(led_classdev_register); -+ -+/** -+ * led_classdev_unregister - unregisters a object of led_properties class. -+ * @led_cdev: the led device to unreigister -+ * -+ * Unregisters a previously registered via led_classdev_register object. -+ */ -+void led_classdev_unregister(struct led_classdev *led_cdev) -+{ -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_brightness); -+#ifdef CONFIG_LEDS_TRIGGERS -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_trigger); -+ write_lock(&led_cdev->trigger_lock); -+ if (led_cdev->trigger) -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+#endif -+ -+ class_device_unregister(led_cdev->class_dev); -+ -+ write_lock(&leds_list_lock); -+ list_del(&led_cdev->node); -+ write_unlock(&leds_list_lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_unregister); -+ -+static int __init leds_init(void) -+{ -+ leds_class = class_create(THIS_MODULE, "leds"); -+ if (IS_ERR(leds_class)) -+ return PTR_ERR(leds_class); -+ return 0; -+} -+ -+static void __exit leds_exit(void) -+{ -+ class_destroy(leds_class); -+} -+ -+subsys_initcall(leds_init); -+module_exit(leds_exit); -+ -+MODULE_AUTHOR("John Lenz, Richard Purdie"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LED Class Interface"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-core.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,25 @@ -+/* -+ * LED Class Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/list.h> -+#include <linux/module.h> -+#include <linux/spinlock.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+rwlock_t leds_list_lock = RW_LOCK_UNLOCKED; -+LIST_HEAD(leds_list); -+ -+EXPORT_SYMBOL_GPL(leds_list); -+EXPORT_SYMBOL_GPL(leds_list_lock); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds.h 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,45 @@ -+/* -+ * LED Core -+ * -+ * Copyright 2005 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef __LEDS_H_INCLUDED -+#define __LEDS_H_INCLUDED -+ -+#include <linux/leds.h> -+ -+/* led_cdev->lock must be held as write */ -+static inline void led_set_brightness(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value > LED_FULL) -+ value = LED_FULL; -+ led_cdev->brightness = value; -+ if (!(led_cdev->flags & LED_SUSPENDED)) -+ led_cdev->brightness_set(led_cdev, value); -+} -+ -+extern rwlock_t leds_list_lock; -+extern struct list_head leds_list; -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+void led_trigger_set_default(struct led_classdev *led_cdev); -+void led_trigger_set(struct led_classdev *led_cdev, -+ struct led_trigger *trigger); -+#else -+#define led_trigger_set_default(x) do {} while(0) -+#define led_trigger_set(x, y) do {} while(0) -+#endif -+ -+ssize_t led_trigger_store(struct class_device *dev, const char *buf, -+ size_t count); -+ssize_t led_trigger_show(struct class_device *dev, char *buf); -+ -+#endif /* __LEDS_H_INCLUDED */ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/Makefile 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,15 @@ -+ -+# LED Core -+obj-$(CONFIG_NEW_LEDS) += led-core.o -+obj-$(CONFIG_LEDS_CLASS) += led-class.o -+obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o -+ -+# LED Platform Drivers -+obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o -+obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o -+obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o -+obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o -+obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o -+ -+# LED Triggers -+obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o ---- linux-ixp4xx.orig/drivers/Makefile 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/Makefile 2006-03-07 22:59:04.000000000 +0100 -@@ -68,6 +68,7 @@ obj-$(CONFIG_MCA) += mca/ - obj-$(CONFIG_EISA) += eisa/ - obj-$(CONFIG_CPU_FREQ) += cpufreq/ - obj-$(CONFIG_MMC) += mmc/ -+obj-$(CONFIG_NEW_LEDS) += leds/ - obj-$(CONFIG_INFINIBAND) += infiniband/ - obj-$(CONFIG_SGI_SN) += sn/ - obj-y += firmware/ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/linux/leds.h 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,105 @@ -+/* -+ * Driver model for leds and led triggers -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * Copyright (C) 2005 Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef __LINUX_LEDS_H_INCLUDED -+#define __LINUX_LEDS_H_INCLUDED -+ -+struct device; -+struct class_device; -+/* -+ * LED Core -+ */ -+ -+enum led_brightness { -+ LED_OFF = 0, -+ LED_HALF = 127, -+ LED_FULL = 255, -+}; -+ -+struct led_classdev { -+ const char *name; -+ int brightness; -+ int flags; -+#define LED_SUSPENDED (1 << 0) -+ -+ /* A function to set the brightness of the led */ -+ void (*brightness_set)(struct led_classdev *led_cdev, -+ enum led_brightness brightness); -+ -+ struct class_device *class_dev; -+ /* LED Device linked list */ -+ struct list_head node; -+ -+ /* Protects the LED properties data above */ -+ rwlock_t lock; -+ -+ /* Trigger data */ -+ char *default_trigger; -+#ifdef CONFIG_LEDS_TRIGGERS -+ rwlock_t trigger_lock; -+ /* Protects the trigger data below */ -+ -+ struct led_trigger *trigger; -+ struct list_head trig_list; -+ void *trigger_data; -+#endif -+}; -+ -+extern int led_classdev_register(struct device *parent, -+ struct led_classdev *led_cdev); -+extern void led_classdev_unregister(struct led_classdev *led_cdev); -+extern void led_classdev_suspend(struct led_classdev *led_cdev); -+extern void led_classdev_resume(struct led_classdev *led_cdev); -+ -+/* -+ * LED Triggers -+ */ -+#ifdef CONFIG_LEDS_TRIGGERS -+ -+#define TRIG_NAME_MAX 50 -+ -+struct led_trigger { -+ /* Trigger Properties */ -+ const char *name; -+ void (*activate)(struct led_classdev *led_cdev); -+ void (*deactivate)(struct led_classdev *led_cdev); -+ -+ /* LEDs under control by this trigger (for simple triggers) */ -+ rwlock_t leddev_list_lock; -+ struct list_head led_cdevs; -+ -+ /* Link to next registered trigger */ -+ struct list_head next_trig; -+}; -+ -+/* Registration functions for complex triggers */ -+int led_trigger_register(struct led_trigger *trigger); -+void led_trigger_unregister(struct led_trigger *trigger); -+ -+/* Registration functions for simple triggers */ -+#define DEFINE_LED_TRIGGER(x) static struct led_trigger *x; -+#define DEFINE_LED_TRIGGER_GLOBAL(x) struct led_trigger *x; -+void led_trigger_register_simple(const char *name, -+ struct led_trigger **trigger); -+void led_trigger_unregister_simple(struct led_trigger *trigger); -+void led_trigger_event(struct led_trigger *trigger, enum led_brightness event); -+ -+#else -+ -+/* Triggers aren't active - null macros */ -+#define DEFINE_LED_TRIGGER(x) -+#define DEFINE_LED_TRIGGER_GLOBAL(x) -+#define led_trigger_register_simple(x, y) do {} while(0) -+#define led_trigger_unregister_simple(x) do {} while(0) -+#define led_trigger_event(x, y) do {} while(0) -+ -+#endif -+#endif /* __LINUX_LEDS_H_INCLUDED */ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-triggers.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,239 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+/* -+ * Nests outside led_cdev->lock and led_cdev->trigger_lock -+ */ -+static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED; -+static LIST_HEAD(trigger_list); -+ -+ssize_t led_trigger_store(struct class_device *dev, const char *buf, -+ size_t count) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ char trigger_name[TRIG_NAME_MAX]; -+ struct led_trigger *trig; -+ size_t len; -+ -+ trigger_name[sizeof(trigger_name) - 1] = '\0'; -+ strncpy(trigger_name, buf, sizeof(trigger_name) - 1); -+ len = strlen(trigger_name); -+ -+ if (len && trigger_name[len - 1] == '\n') -+ trigger_name[len - 1] = '\0'; -+ -+ if (!strcmp(trigger_name, "none")) { -+ write_lock(&led_cdev->trigger_lock); -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+ return count; -+ } -+ -+ read_lock(&triggers_list_lock); -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (!strcmp(trigger_name, trig->name)) { -+ write_lock(&led_cdev->trigger_lock); -+ led_trigger_set(led_cdev, trig); -+ write_unlock(&led_cdev->trigger_lock); -+ -+ read_unlock(&triggers_list_lock); -+ return count; -+ } -+ } -+ read_unlock(&triggers_list_lock); -+ -+ return -EINVAL; -+} -+ -+ -+ssize_t led_trigger_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct led_trigger *trig; -+ int len = 0; -+ -+ read_lock(&triggers_list_lock); -+ read_lock(&led_cdev->trigger_lock); -+ -+ if (!led_cdev->trigger) -+ len += sprintf(buf+len, "[none] "); -+ else -+ len += sprintf(buf+len, "none "); -+ -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, -+ trig->name)) -+ len += sprintf(buf+len, "[%s] ", trig->name); -+ else -+ len += sprintf(buf+len, "%s ", trig->name); -+ } -+ read_unlock(&led_cdev->trigger_lock); -+ read_unlock(&triggers_list_lock); -+ -+ len += sprintf(len+buf, "\n"); -+ return len; -+} -+ -+void led_trigger_event(struct led_trigger *trigger, -+ enum led_brightness brightness) -+{ -+ struct list_head *entry; -+ -+ if (!trigger) -+ return; -+ -+ read_lock(&trigger->leddev_list_lock); -+ list_for_each(entry, &trigger->led_cdevs) { -+ struct led_classdev *led_cdev; -+ -+ led_cdev = list_entry(entry, struct led_classdev, trig_list); -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, brightness); -+ write_unlock(&led_cdev->lock); -+ } -+ read_unlock(&trigger->leddev_list_lock); -+} -+ -+/* Caller must ensure led_cdev->trigger_lock held */ -+void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) -+{ -+ /* Remove any existing trigger */ -+ if (led_cdev->trigger) { -+ write_lock(&led_cdev->trigger->leddev_list_lock); -+ list_del(&led_cdev->trig_list); -+ write_unlock(&led_cdev->trigger->leddev_list_lock); -+ if (led_cdev->trigger->deactivate) -+ led_cdev->trigger->deactivate(led_cdev); -+ } -+ if (trigger) { -+ write_lock(&trigger->leddev_list_lock); -+ list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs); -+ write_unlock(&trigger->leddev_list_lock); -+ if (trigger->activate) -+ trigger->activate(led_cdev); -+ } -+ led_cdev->trigger = trigger; -+} -+ -+void led_trigger_set_default(struct led_classdev *led_cdev) -+{ -+ struct led_trigger *trig; -+ -+ if (!led_cdev->default_trigger) -+ return; -+ -+ read_lock(&triggers_list_lock); -+ write_lock(&led_cdev->trigger_lock); -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (!strcmp(led_cdev->default_trigger, trig->name)) -+ led_trigger_set(led_cdev, trig); -+ } -+ write_unlock(&led_cdev->trigger_lock); -+ read_unlock(&triggers_list_lock); -+} -+ -+int led_trigger_register(struct led_trigger *trigger) -+{ -+ struct led_classdev *led_cdev; -+ -+ rwlock_init(&trigger->leddev_list_lock); -+ INIT_LIST_HEAD(&trigger->led_cdevs); -+ -+ /* Add to the list of led triggers */ -+ write_lock(&triggers_list_lock); -+ list_add_tail(&trigger->next_trig, &trigger_list); -+ write_unlock(&triggers_list_lock); -+ -+ /* Register with any LEDs that have this as a default trigger */ -+ read_lock(&leds_list_lock); -+ list_for_each_entry(led_cdev, &leds_list, node) { -+ write_lock(&led_cdev->trigger_lock); -+ if (!led_cdev->trigger && led_cdev->default_trigger && -+ !strcmp(led_cdev->default_trigger, trigger->name)) -+ led_trigger_set(led_cdev, trigger); -+ write_unlock(&led_cdev->trigger_lock); -+ } -+ read_unlock(&leds_list_lock); -+ -+ return 0; -+} -+ -+void led_trigger_register_simple(const char *name, struct led_trigger **tp) -+{ -+ struct led_trigger *trigger; -+ -+ trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); -+ -+ if (trigger) { -+ trigger->name = name; -+ led_trigger_register(trigger); -+ } -+ *tp = trigger; -+} -+ -+void led_trigger_unregister(struct led_trigger *trigger) -+{ -+ struct led_classdev *led_cdev; -+ -+ /* Remove from the list of led triggers */ -+ write_lock(&triggers_list_lock); -+ list_del(&trigger->next_trig); -+ write_unlock(&triggers_list_lock); -+ -+ /* Remove anyone actively using this trigger */ -+ read_lock(&leds_list_lock); -+ list_for_each_entry(led_cdev, &leds_list, node) { -+ write_lock(&led_cdev->trigger_lock); -+ if (led_cdev->trigger == trigger) -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+ } -+ read_unlock(&leds_list_lock); -+} -+ -+void led_trigger_unregister_simple(struct led_trigger *trigger) -+{ -+ led_trigger_unregister(trigger); -+ kfree(trigger); -+} -+ -+/* Used by LED Class */ -+EXPORT_SYMBOL_GPL(led_trigger_set); -+EXPORT_SYMBOL_GPL(led_trigger_set_default); -+EXPORT_SYMBOL_GPL(led_trigger_show); -+EXPORT_SYMBOL_GPL(led_trigger_store); -+ -+/* LED Trigger Interface */ -+EXPORT_SYMBOL_GPL(led_trigger_register); -+EXPORT_SYMBOL_GPL(led_trigger_unregister); -+ -+/* Simple LED Tigger Interface */ -+EXPORT_SYMBOL_GPL(led_trigger_register_simple); -+EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); -+EXPORT_SYMBOL_GPL(led_trigger_event); -+ -+MODULE_AUTHOR("Richard Purdie"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LED Triggers Core"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/ledtrig-timer.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,174 @@ -+/* -+ * LED Kernel Timer Trigger -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+struct timer_trig_data { -+ unsigned long delay_on; /* milliseconds on */ -+ unsigned long delay_off; /* milliseconds off */ -+ struct timer_list timer; -+}; -+ -+static void led_timer_function(unsigned long data) -+{ -+ struct led_classdev *led_cdev = (struct led_classdev *) data; -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ unsigned long brightness = LED_OFF; -+ unsigned long delay = timer_data->delay_off; -+ -+ if (!timer_data->delay_on || !timer_data->delay_off) { -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, LED_OFF); -+ write_unlock(&led_cdev->lock); -+ return; -+ } -+ -+ if (!led_cdev->brightness) { -+ brightness = LED_FULL; -+ delay = timer_data->delay_on; -+ } -+ -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, brightness); -+ write_unlock(&led_cdev->lock); -+ -+ mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); -+} -+ -+static ssize_t led_delay_on_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ sprintf(buf, "%lu\n", timer_data->delay_on); -+ -+ return strlen(buf) + 1; -+} -+ -+static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, -+ size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ int ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ timer_data->delay_on = state; -+ mod_timer(&timer_data->timer, jiffies + 1); -+ ret = after - buf; -+ } -+ -+ return ret; -+} -+ -+static ssize_t led_delay_off_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ sprintf(buf, "%lu\n", timer_data->delay_off); -+ -+ return strlen(buf) + 1; -+} -+ -+static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, -+ size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ int ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ timer_data->delay_off = state; -+ mod_timer(&timer_data->timer, jiffies + 1); -+ ret = after - buf; -+ } -+ -+ return ret; -+} -+ -+static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, -+ led_delay_on_store); -+static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, -+ led_delay_off_store); -+ -+static void timer_trig_activate(struct led_classdev *led_cdev) -+{ -+ struct timer_trig_data *timer_data; -+ -+ timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); -+ if (!timer_data) -+ return; -+ -+ led_cdev->trigger_data = timer_data; -+ -+ init_timer(&timer_data->timer); -+ timer_data->timer.function = led_timer_function; -+ timer_data->timer.data = (unsigned long) led_cdev; -+ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_delay_on); -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_delay_off); -+} -+ -+static void timer_trig_deactivate(struct led_classdev *led_cdev) -+{ -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ if (timer_data) { -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_delay_on); -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_delay_off); -+ del_timer_sync(&timer_data->timer); -+ kfree(timer_data); -+ } -+} -+ -+static struct led_trigger timer_led_trigger = { -+ .name = "timer", -+ .activate = timer_trig_activate, -+ .deactivate = timer_trig_deactivate, -+}; -+ -+static int __init timer_trig_init(void) -+{ -+ return led_trigger_register(&timer_led_trigger); -+} -+ -+static void __exit timer_trig_exit(void) -+{ -+ led_trigger_unregister(&timer_led_trigger); -+} -+ -+module_init(timer_trig_init); -+module_exit(timer_trig_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Timer LED trigger"); -+MODULE_LICENSE("GPL"); ---- linux-ixp4xx.orig/arch/arm/mach-pxa/corgi.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/corgi.c 2006-03-07 22:59:04.000000000 +0100 -@@ -165,6 +165,14 @@ static struct platform_device corgikbd_d - - - /* -+ * Corgi LEDs -+ */ -+static struct platform_device corgiled_device = { -+ .name = "corgi-led", -+ .id = -1, -+}; -+ -+/* - * Corgi Touch Screen Device - */ - static struct resource corgits_resources[] = { -@@ -298,6 +306,7 @@ static struct platform_device *devices[] - &corgikbd_device, - &corgibl_device, - &corgits_device, -+ &corgiled_device, - }; - - static void __init corgi_init(void) ---- linux-ixp4xx.orig/arch/arm/mach-pxa/spitz.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/spitz.c 2006-03-07 22:59:04.000000000 +0100 -@@ -243,6 +243,14 @@ static struct platform_device spitzkbd_d - - - /* -+ * Spitz LEDs -+ */ -+static struct platform_device spitzled_device = { -+ .name = "spitz-led", -+ .id = -1, -+}; -+ -+/* - * Spitz Touch Screen Device - */ - static struct resource spitzts_resources[] = { -@@ -419,6 +427,7 @@ static struct platform_device *devices[] - &spitzkbd_device, - &spitzts_device, - &spitzbl_device, -+ &spitzled_device, - }; - - static void __init common_init(void) ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-corgi.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,121 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/mach-types.h> -+#include <asm/arch/corgi.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/hardware/scoop.h> -+ -+static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); -+ else -+ GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); -+} -+ -+static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); -+ else -+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); -+} -+ -+static struct led_classdev corgi_amber_led = { -+ .name = "corgi:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = corgiled_amber_set, -+}; -+ -+static struct led_classdev corgi_green_led = { -+ .name = "corgi:green", -+ .default_trigger = "nand-disk", -+ .brightness_set = corgiled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int corgiled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&corgi_amber_led); -+ led_classdev_suspend(&corgi_green_led); -+ return 0; -+} -+ -+static int corgiled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&corgi_amber_led); -+ led_classdev_resume(&corgi_green_led); -+ return 0; -+} -+#endif -+ -+static int corgiled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&pdev->dev, &corgi_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &corgi_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&corgi_amber_led); -+ -+ return ret; -+} -+ -+static int corgiled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&corgi_amber_led); -+ led_classdev_unregister(&corgi_green_led); -+ return 0; -+} -+ -+static struct platform_driver corgiled_driver = { -+ .probe = corgiled_probe, -+ .remove = corgiled_remove, -+#ifdef CONFIG_PM -+ .suspend = corgiled_suspend, -+ .resume = corgiled_resume, -+#endif -+ .driver = { -+ .name = "corgi-led", -+ }, -+}; -+ -+static int __init corgiled_init(void) -+{ -+ return platform_driver_register(&corgiled_driver); -+} -+ -+static void __exit corgiled_exit(void) -+{ -+ platform_driver_unregister(&corgiled_driver); -+} -+ -+module_init(corgiled_init); -+module_exit(corgiled_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Corgi LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-spitz.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,125 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/hardware/scoop.h> -+#include <asm/mach-types.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/spitz.h> -+ -+static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); -+ else -+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); -+} -+ -+static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); -+ else -+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); -+} -+ -+static struct led_classdev spitz_amber_led = { -+ .name = "spitz:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = spitzled_amber_set, -+}; -+ -+static struct led_classdev spitz_green_led = { -+ .name = "spitz:green", -+ .default_trigger = "ide-disk", -+ .brightness_set = spitzled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int spitzled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&spitz_amber_led); -+ led_classdev_suspend(&spitz_green_led); -+ return 0; -+} -+ -+static int spitzled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&spitz_amber_led); -+ led_classdev_resume(&spitz_green_led); -+ return 0; -+} -+#endif -+ -+static int spitzled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ if (machine_is_akita()) -+ spitz_green_led.default_trigger = "nand-disk"; -+ -+ ret = led_classdev_register(&pdev->dev, &spitz_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &spitz_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&spitz_amber_led); -+ -+ return ret; -+} -+ -+static int spitzled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&spitz_amber_led); -+ led_classdev_unregister(&spitz_green_led); -+ -+ return 0; -+} -+ -+static struct platform_driver spitzled_driver = { -+ .probe = spitzled_probe, -+ .remove = spitzled_remove, -+#ifdef CONFIG_PM -+ .suspend = spitzled_suspend, -+ .resume = spitzled_resume, -+#endif -+ .driver = { -+ .name = "spitz-led", -+ }, -+}; -+ -+static int __init spitzled_init(void) -+{ -+ return platform_driver_register(&spitzled_driver); -+} -+ -+static void __exit spitzled_exit(void) -+{ -+ platform_driver_unregister(&spitzled_driver); -+} -+ -+module_init(spitzled_init); -+module_exit(spitzled_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Spitz LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-locomo.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,95 @@ -+/* -+ * linux/drivers/leds/locomo.c -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/device.h> -+#include <linux/leds.h> -+ -+#include <asm/hardware.h> -+#include <asm/hardware/locomo.h> -+ -+static void locomoled_brightness_set(struct led_classdev *led_cdev, -+ enum led_brightness value, int offset) -+{ -+ struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (value) -+ locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset); -+ else -+ locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset); -+ local_irq_restore(flags); -+} -+ -+static void locomoled_brightness_set0(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0); -+} -+ -+static void locomoled_brightness_set1(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1); -+} -+ -+static struct led_classdev locomo_led0 = { -+ .name = "locomo:amber", -+ .brightness_set = locomoled_brightness_set0, -+}; -+ -+static struct led_classdev locomo_led1 = { -+ .name = "locomo:green", -+ .brightness_set = locomoled_brightness_set1, -+}; -+ -+static int locomoled_probe(struct locomo_dev *ldev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&ldev->dev, &locomo_led0); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&ldev->dev, &locomo_led1); -+ if (ret < 0) -+ led_classdev_unregister(&locomo_led0); -+ -+ return ret; -+} -+ -+static int locomoled_remove(struct locomo_dev *dev) -+{ -+ led_classdev_unregister(&locomo_led0); -+ led_classdev_unregister(&locomo_led1); -+ return 0; -+} -+ -+static struct locomo_driver locomoled_driver = { -+ .drv = { -+ .name = "locomoled" -+ }, -+ .devid = LOCOMO_DEVID_LED, -+ .probe = locomoled_probe, -+ .remove = locomoled_remove, -+}; -+ -+static int __init locomoled_init(void) -+{ -+ return locomo_driver_register(&locomoled_driver); -+} -+module_init(locomoled_init); -+ -+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); -+MODULE_DESCRIPTION("Locomo LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-ixp4xx-gpio.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,215 @@ -+/* -+ * IXP4XX GPIO driver LED driver -+ * -+ * Author: John Bowler <jbowler@acm.org> -+ * -+ * Copyright (c) 2006 John Bowler -+ * -+ * Permission is hereby granted, free of charge, to any -+ * person obtaining a copy of this software and associated -+ * documentation files (the "Software"), to deal in the -+ * Software without restriction, including without -+ * limitation the rights to use, copy, modify, merge, -+ * publish, distribute, sublicense, and/or sell copies of -+ * the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the -+ * following conditions: -+ * -+ * The above copyright notice and this permission notice -+ * shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/spinlock.h> -+#include <linux/leds.h> -+#include <asm/arch/hardware.h> -+ -+extern spinlock_t gpio_lock; -+ -+/* Up to 16 gpio lines are possible. */ -+#define GPIO_MAX 16 -+static struct ixp4xxgpioled_device { -+ struct led_classdev ancestor; -+ int flags; -+} ixp4xxgpioled_devices[GPIO_MAX]; -+ -+void ixp4xxgpioled_brightness_set(struct led_classdev *pled, -+ enum led_brightness value) -+{ -+ const struct ixp4xxgpioled_device *const ixp4xx_dev = -+ container_of(pled, struct ixp4xxgpioled_device, ancestor); -+ const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices; -+ -+ if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) { -+ /* Set or clear the 'gpio_pin' bit according to the style -+ * and the required setting (value > 0 == on) -+ */ -+ const int gpio_value = -+ (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ? -+ IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW; -+ -+ { -+ unsigned long flags; -+ spin_lock_irqsave(&gpio_lock, flags); -+ gpio_line_set(gpio_pin, gpio_value); -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ } -+ } -+} -+ -+/* LEDs are described in resources, the following iterates over the valid -+ * LED resources. -+ */ -+#define for_all_leds(i, pdev) \ -+ for (i=0; i<pdev->num_resources; ++i) \ -+ if (pdev->resource[i].start < GPIO_MAX && \ -+ pdev->resource[i].name != 0) -+ -+/* The following applies 'operation' to each LED from the given platform, -+ * the function always returns 0 to allow tail call elimination. -+ */ -+static int apply_to_all_leds(struct platform_device *pdev, -+ void (*operation)(struct led_classdev *pled)) -+{ -+ int i; -+ -+ for_all_leds(i, pdev) -+ operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ixp4xxgpioled_suspend(struct platform_device *pdev, -+ pm_message_t state) -+{ -+ return apply_to_all_leds(pdev, led_classdev_suspend); -+} -+ -+static int ixp4xxgpioled_resume(struct platform_device *pdev) -+{ -+ return apply_to_all_leds(pdev, led_classdev_resume); -+} -+#endif -+ -+static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled) -+{ -+ led_classdev_unregister(pled); -+ pled->name = 0; -+} -+ -+static int ixp4xxgpioled_remove(struct platform_device *pdev) -+{ -+ return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led); -+} -+ -+static int ixp4xxgpioled_probe(struct platform_device *pdev) -+{ -+ /* The board level has to tell the driver where the -+ * LEDs are connected - there is no way to find out -+ * electrically. It must also say whether the GPIO -+ * lines are active high or active low. -+ * -+ * To do this read the num_resources (the number of -+ * LEDs) and the struct resource (the data for each -+ * LED). The name comes from the resource, and it -+ * isn't copied. -+ */ -+ int i; -+ -+ for_all_leds(i, pdev) { -+ const u8 gpio_pin = pdev->resource[i].start; -+ int rc; -+ -+ if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT); -+ /* The config can, apparently, reset the state, -+ * I suspect the gpio line may be an input and -+ * the config may cause the line to be latched, -+ * so the setting depends on how the LED is -+ * connected to the line (which affects how it -+ * floats if not driven). -+ */ -+ gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH); -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ -+ ixp4xxgpioled_devices[gpio_pin].flags = -+ pdev->resource[i].flags & IORESOURCE_BITS; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.name = -+ pdev->resource[i].name; -+ -+ /* This is how a board manufacturer makes the LED -+ * come on on reset - the GPIO line will be high, so -+ * make the LED light when the line is low... -+ */ -+ if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW) -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100; -+ else -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set = -+ ixp4xxgpioled_brightness_set; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0; -+ } -+ -+ rc = led_classdev_register(&pdev->dev, -+ &ixp4xxgpioled_devices[gpio_pin].ancestor); -+ if (rc < 0) { -+ ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0; -+ ixp4xxgpioled_remove(pdev); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver ixp4xxgpioled_driver = { -+ .probe = ixp4xxgpioled_probe, -+ .remove = ixp4xxgpioled_remove, -+#ifdef CONFIG_PM -+ .suspend = ixp4xxgpioled_suspend, -+ .resume = ixp4xxgpioled_resume, -+#endif -+ .driver = { -+ .name = "IXP4XX-GPIO-LED", -+ }, -+}; -+ -+static int __init ixp4xxgpioled_init(void) -+{ -+ return platform_driver_register(&ixp4xxgpioled_driver); -+} -+ -+static void __exit ixp4xxgpioled_exit(void) -+{ -+ platform_driver_unregister(&ixp4xxgpioled_driver); -+} -+ -+module_init(ixp4xxgpioled_init); -+module_exit(ixp4xxgpioled_exit); -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("IXP4XX GPIO LED driver"); -+MODULE_LICENSE("Dual MIT/GPL"); ---- linux-ixp4xx.orig/arch/arm/mach-pxa/tosa.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/tosa.c 2006-03-07 22:59:04.000000000 +0100 -@@ -252,10 +252,19 @@ static struct platform_device tosakbd_de - .id = -1, - }; - -+/* -+ * Tosa LEDs -+ */ -+static struct platform_device tosaled_device = { -+ .name = "tosa-led", -+ .id = -1, -+}; -+ - static struct platform_device *devices[] __initdata = { - &tosascoop_device, - &tosascoop_jc_device, - &tosakbd_device, -+ &tosaled_device, - }; - - static void __init tosa_init(void) ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-tosa.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,131 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005 Dirk Opfer -+ * -+ * Author: Dirk Opfer <Dirk@Opfer-Online.de> -+ * based on spitz.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/hardware/scoop.h> -+#include <asm/mach-types.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/tosa.h> -+ -+static void tosaled_amber_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_CHRG_ERR_LED); -+ else -+ reset_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_CHRG_ERR_LED); -+} -+ -+static void tosaled_green_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_NOTE_LED); -+ else -+ reset_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_NOTE_LED); -+} -+ -+static struct led_classdev tosa_amber_led = { -+ .name = "tosa:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = tosaled_amber_set, -+}; -+ -+static struct led_classdev tosa_green_led = { -+ .name = "tosa:green", -+ .default_trigger = "nand-disk", -+ .brightness_set = tosaled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int tosaled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name, -+ "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&tosa_amber_led); -+ led_classdev_suspend(&tosa_green_led); -+ return 0; -+} -+ -+static int tosaled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&tosa_amber_led); -+ led_classdev_resume(&tosa_green_led); -+ return 0; -+} -+#else -+#define tosaled_suspend NULL -+#define tosaled_resume NULL -+#endif -+ -+static int tosaled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&pdev->dev, &tosa_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &tosa_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&tosa_amber_led); -+ -+ return ret; -+} -+ -+static int tosaled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&tosa_amber_led); -+ led_classdev_unregister(&tosa_green_led); -+ -+ return 0; -+} -+ -+static struct platform_driver tosaled_driver = { -+ .probe = tosaled_probe, -+ .remove = tosaled_remove, -+ .suspend = tosaled_suspend, -+ .resume = tosaled_resume, -+ .driver = { -+ .name = "tosa-led", -+ }, -+}; -+ -+static int __init tosaled_init(void) -+{ -+ return platform_driver_register(&tosaled_driver); -+} -+ -+static void __exit tosaled_exit(void) -+{ -+ platform_driver_unregister(&tosaled_driver); -+} -+ -+module_init(tosaled_init); -+module_exit(tosaled_exit); -+ -+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); -+MODULE_DESCRIPTION("Tosa LED driver"); -+MODULE_LICENSE("GPL"); ---- linux-ixp4xx.orig/drivers/ide/ide-disk.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/ide/ide-disk.c 2006-03-07 22:59:04.000000000 +0100 -@@ -60,6 +60,7 @@ - #include <linux/genhd.h> - #include <linux/slab.h> - #include <linux/delay.h> -+#include <linux/leds.h> - - #define _IDE_DISK - -@@ -80,6 +81,8 @@ struct ide_disk_obj { - - static DECLARE_MUTEX(idedisk_ref_sem); - -+DEFINE_LED_TRIGGER(ide_led_trigger); -+ - #define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) - - #define ide_disk_g(disk) \ -@@ -298,6 +301,13 @@ static ide_startstop_t __ide_do_rw_disk( - } - } - -+static int ide_end_rw_disk(ide_drive_t *drive, int uptodate, int nr_sectors) -+{ -+ if (blk_fs_request(HWGROUP(drive)->rq)) -+ led_trigger_event(ide_led_trigger, LED_OFF); -+ return ide_end_request(drive, uptodate, nr_sectors); -+} -+ - /* - * 268435455 == 137439 MB or 28bit limit - * 320173056 == 163929 MB or 48bit addressing -@@ -312,10 +322,12 @@ static ide_startstop_t ide_do_rw_disk (i - - if (!blk_fs_request(rq)) { - blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); -- ide_end_request(drive, 0, 0); -+ ide_end_rw_disk(drive, 0, 0); - return ide_stopped; - } - -+ led_trigger_event(ide_led_trigger, LED_FULL); -+ - pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", - drive->name, rq_data_dir(rq) == READ ? "read" : "writ", - (unsigned long long)block, rq->nr_sectors, -@@ -1063,7 +1075,7 @@ static ide_driver_t idedisk_driver = { - .media = ide_disk, - .supports_dsc_overlap = 0, - .do_request = ide_do_rw_disk, -- .end_request = ide_end_request, -+ .end_request = ide_end_rw_disk, - .error = __ide_error, - .abort = __ide_abort, - .proc = idedisk_proc, -@@ -1236,12 +1248,16 @@ failed: - - static void __exit idedisk_exit (void) - { -+ led_trigger_unregister_simple(ide_led_trigger); - driver_unregister(&idedisk_driver.gen_driver); - } - - static int __init idedisk_init(void) - { -- return driver_register(&idedisk_driver.gen_driver); -+ int ret = driver_register(&idedisk_driver.gen_driver); -+ if (ret >= 0) -+ led_trigger_register_simple("ide-disk", &ide_led_trigger); -+ return ret; - } - - MODULE_ALIAS("ide:*m-disk*"); ---- linux-ixp4xx.orig/drivers/mtd/nand/nand_base.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/mtd/nand/nand_base.c 2006-03-07 22:59:04.000000000 +0100 -@@ -80,6 +80,7 @@ - #include <linux/mtd/compatmac.h> - #include <linux/interrupt.h> - #include <linux/bitops.h> -+#include <linux/leds.h> - #include <asm/io.h> - - #ifdef CONFIG_MTD_PARTITIONS -@@ -515,6 +516,8 @@ static int nand_block_checkbad (struct m - return nand_isbad_bbt (mtd, ofs, allowbbt); - } - -+DEFINE_LED_TRIGGER(nand_led_trigger); -+ - /* - * Wait for the ready pin, after a command - * The timeout is catched later. -@@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_i - struct nand_chip *this = mtd->priv; - unsigned long timeo = jiffies + 2; - -+ led_trigger_event(nand_led_trigger, LED_FULL); - /* wait until command is processed or timeout occures */ - do { - if (this->dev_ready(mtd)) -- return; -+ break; - touch_softlockup_watchdog(); - } while (time_before(jiffies, timeo)); -+ led_trigger_event(nand_led_trigger, LED_OFF); - } - - /** -@@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mt - else - timeo += (HZ * 20) / 1000; - -+ led_trigger_event(nand_led_trigger, LED_FULL); -+ - /* Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. */ - ndelay (100); -@@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mt - } - cond_resched(); - } -+ led_trigger_event(nand_led_trigger, LED_OFF); -+ - status = (int) this->read_byte(mtd); - return status; - } -@@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd) - EXPORT_SYMBOL_GPL (nand_scan); - EXPORT_SYMBOL_GPL (nand_release); - -+ -+static int __init nand_base_init(void) -+{ -+ led_trigger_register_simple("nand-disk", &nand_led_trigger); -+ return 0; -+} -+ -+static void __exit nand_base_exit(void) -+{ -+ led_trigger_unregister_simple(nand_led_trigger); -+} -+ -+module_init(nand_base_init); -+module_exit(nand_base_exit); -+ - MODULE_LICENSE ("GPL"); - MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); - MODULE_DESCRIPTION ("Generic NAND flash driver code"); diff --git a/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch b/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch deleted file mode 100644 index 86c88c3746..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch +++ /dev/null @@ -1,13671 +0,0 @@ ---- linux-2.6.16.orig/include/linux/hwmon-sysfs.h 2006-03-22 17:06:11.000000000 +0100 -+++ linux-2.6.16/include/linux/hwmon-sysfs.h 2006-03-22 17:06:15.000000000 +0100 -@@ -27,11 +27,13 @@ - #define to_sensor_dev_attr(_dev_attr) \ - container_of(_dev_attr, struct sensor_device_attribute, dev_attr) - --#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \ --struct sensor_device_attribute sensor_dev_attr_##_name = { \ -- .dev_attr = __ATTR(_name,_mode,_show,_store), \ -- .index = _index, \ --} -+#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ -+ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ -+ .index = _index } -+ -+#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ -+struct sensor_device_attribute sensor_dev_attr_##_name \ -+ = SENSOR_ATTR(_name, _mode, _show, _store, _index) - - struct sensor_device_attribute_2 { - struct device_attribute dev_attr; -@@ -41,11 +43,13 @@ - #define to_sensor_dev_attr_2(_dev_attr) \ - container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) - -+#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \ -+ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ -+ .index = _index, \ -+ .nr = _nr } -+ - #define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ --struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ -- .dev_attr = __ATTR(_name,_mode,_show,_store), \ -- .index = _index, \ -- .nr = _nr, \ --} -+struct sensor_device_attribute_2 sensor_dev_attr_##_name \ -+ = SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) - - #endif /* _LINUX_HWMON_SYSFS_H */ ---- linux-2.6.16.orig/drivers/hwmon/pc87360.c 2006-03-22 17:06:11.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/pc87360.c 2006-03-22 17:06:15.000000000 +0100 -@@ -43,6 +43,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - static u8 devid; -@@ -183,8 +184,8 @@ - struct pc87360_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -- struct semaphore update_lock; -+ struct mutex lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -283,7 +284,7 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long fan_min = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); - - /* If it wouldn't fit, change clock divisor */ -@@ -300,23 +301,31 @@ - /* Write new divider, preserve alarm bits */ - pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), - data->fan_status[attr->index] & 0xF9); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --#define show_and_set_fan(offset) \ --static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ -- show_fan_input, NULL, offset-1); \ --static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \ -- show_fan_min, set_fan_min, offset-1); \ --static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ -- show_fan_div, NULL, offset-1); \ --static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \ -- show_fan_status, NULL, offset-1); --show_and_set_fan(1) --show_and_set_fan(2) --show_and_set_fan(3) -+static struct sensor_device_attribute fan_input[] = { -+ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), -+ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), -+ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), -+}; -+static struct sensor_device_attribute fan_status[] = { -+ SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), -+ SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), -+ SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), -+}; -+static struct sensor_device_attribute fan_div[] = { -+ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), -+ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), -+ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), -+}; -+static struct sensor_device_attribute fan_min[] = { -+ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), -+ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), -+ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), -+}; - - static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) - { -@@ -335,21 +344,20 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[attr->index] = PWM_TO_REG(val, - FAN_CONFIG_INVERT(data->fan_conf, attr->index)); - pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), - data->pwm[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - --#define show_and_set_pwm(offset) \ --static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \ -- show_pwm, set_pwm, offset-1); --show_and_set_pwm(1) --show_and_set_pwm(2) --show_and_set_pwm(3) -+static struct sensor_device_attribute pwm[] = { -+ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), -+ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), -+ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), -+}; - - static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) - { -@@ -386,11 +394,11 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, - data->in_min[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, -@@ -401,35 +409,67 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, - data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, - data->in_max[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - --#define show_and_set_in(offset) \ --static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ -- show_in_input, NULL, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ -- show_in_min, set_in_min, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ -- show_in_max, set_in_max, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \ -- show_in_status, NULL, offset); --show_and_set_in(0) --show_and_set_in(1) --show_and_set_in(2) --show_and_set_in(3) --show_and_set_in(4) --show_and_set_in(5) --show_and_set_in(6) --show_and_set_in(7) --show_and_set_in(8) --show_and_set_in(9) --show_and_set_in(10) -+static struct sensor_device_attribute in_input[] = { -+ SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), -+ SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), -+ SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), -+ SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), -+ SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), -+ SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), -+ SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), -+ SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), -+ SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), -+ SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), -+ SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), -+}; -+static struct sensor_device_attribute in_status[] = { -+ SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), -+ SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), -+ SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), -+ SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), -+ SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), -+ SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), -+ SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), -+ SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), -+ SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), -+ SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), -+ SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), -+}; -+static struct sensor_device_attribute in_min[] = { -+ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), -+ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), -+ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), -+ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), -+ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), -+ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), -+ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), -+ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), -+ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), -+ SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), -+ SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), -+}; -+static struct sensor_device_attribute in_max[] = { -+ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), -+ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), -+ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), -+ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), -+ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), -+ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), -+ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), -+ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), -+ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), -+ SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), -+ SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), -+}; - - static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) - { -@@ -473,11 +513,11 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, - data->in_min[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, -@@ -488,11 +528,11 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, - data->in_max[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, -@@ -503,28 +543,51 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, - data->in_crit[attr->index-11]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - --#define show_and_set_therm(offset) \ --static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ -- show_therm_input, NULL, 11+offset-4); \ --static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ -- show_therm_min, set_therm_min, 11+offset-4); \ --static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ -- show_therm_max, set_therm_max, 11+offset-4); \ --static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ -- show_therm_crit, set_therm_crit, 11+offset-4); \ --static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ -- show_therm_status, NULL, 11+offset-4); --show_and_set_therm(4) --show_and_set_therm(5) --show_and_set_therm(6) -+/* the +11 term below reflects the fact that VLM units 11,12,13 are -+ used in the chip to measure voltage across the thermistors -+*/ -+static struct sensor_device_attribute therm_input[] = { -+ SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11), -+ SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11), -+ SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11), -+}; -+static struct sensor_device_attribute therm_status[] = { -+ SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11), -+ SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11), -+ SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11), -+}; -+static struct sensor_device_attribute therm_min[] = { -+ SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, -+ show_therm_min, set_therm_min, 0+11), -+ SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, -+ show_therm_min, set_therm_min, 1+11), -+ SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, -+ show_therm_min, set_therm_min, 2+11), -+}; -+static struct sensor_device_attribute therm_max[] = { -+ SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, -+ show_therm_max, set_therm_max, 0+11), -+ SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, -+ show_therm_max, set_therm_max, 1+11), -+ SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, -+ show_therm_max, set_therm_max, 2+11), -+}; -+static struct sensor_device_attribute therm_crit[] = { -+ SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, -+ show_therm_crit, set_therm_crit, 0+11), -+ SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, -+ show_therm_crit, set_therm_crit, 1+11), -+ SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, -+ show_therm_crit, set_therm_crit, 2+11), -+}; - - static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -592,11 +655,11 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, - data->temp_min[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, -@@ -607,11 +670,11 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, - data->temp_max[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, -@@ -622,28 +685,48 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_crit[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, - data->temp_crit[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - --#define show_and_set_temp(offset) \ --static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ -- show_temp_input, NULL, offset-1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ -- show_temp_min, set_temp_min, offset-1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ -- show_temp_max, set_temp_max, offset-1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ -- show_temp_crit, set_temp_crit, offset-1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ -- show_temp_status, NULL, offset-1); --show_and_set_temp(1) --show_and_set_temp(2) --show_and_set_temp(3) -+static struct sensor_device_attribute temp_input[] = { -+ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), -+ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), -+ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), -+}; -+static struct sensor_device_attribute temp_status[] = { -+ SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), -+ SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), -+ SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), -+}; -+static struct sensor_device_attribute temp_min[] = { -+ SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, -+ show_temp_min, set_temp_min, 0), -+ SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, -+ show_temp_min, set_temp_min, 1), -+ SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, -+ show_temp_min, set_temp_min, 2), -+}; -+static struct sensor_device_attribute temp_max[] = { -+ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 0), -+ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 1), -+ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 2), -+}; -+static struct sensor_device_attribute temp_crit[] = { -+ SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, -+ show_temp_crit, set_temp_crit, 0), -+ SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, -+ show_temp_crit, set_temp_crit, 1), -+ SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, -+ show_temp_crit, set_temp_crit, 2), -+}; - - static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -749,22 +832,24 @@ - static int pc87360_detect(struct i2c_adapter *adapter) - { - int i; -- struct i2c_client *new_client; -+ struct i2c_client *client; - struct pc87360_data *data; - int err = 0; - const char *name = "pc87360"; - int use_thermistors = 0; -+ struct device *dev; - - if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) - return -ENOMEM; - -- new_client = &data->client; -- i2c_set_clientdata(new_client, data); -- new_client->addr = address; -- init_MUTEX(&data->lock); -- new_client->adapter = adapter; -- new_client->driver = &pc87360_driver; -- new_client->flags = 0; -+ client = &data->client; -+ dev = &client->dev; -+ i2c_set_clientdata(client, data); -+ client->addr = address; -+ mutex_init(&data->lock); -+ client->adapter = adapter; -+ client->driver = &pc87360_driver; -+ client->flags = 0; - - data->fannr = 2; - data->innr = 0; -@@ -792,15 +877,15 @@ - break; - } - -- strcpy(new_client->name, name); -+ strlcpy(client->name, name, sizeof(client->name)); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - for (i = 0; i < 3; i++) { - if (((data->address[i] = extra_isa[i])) - && !request_region(extra_isa[i], PC87360_EXTENT, - pc87360_driver.driver.name)) { -- dev_err(&new_client->dev, "Region 0x%x-0x%x already " -+ dev_err(&client->dev, "Region 0x%x-0x%x already " - "in use!\n", extra_isa[i], - extra_isa[i]+PC87360_EXTENT-1); - for (i--; i >= 0; i--) -@@ -814,7 +899,7 @@ - if (data->fannr) - data->fan_conf = confreg[0] | (confreg[1] << 8); - -- if ((err = i2c_attach_client(new_client))) -+ if ((err = i2c_attach_client(client))) - goto ERROR2; - - /* Use the correct reference voltage -@@ -828,7 +913,7 @@ - PC87365_REG_TEMP_CONFIG); - } - data->in_vref = (i&0x02) ? 3025 : 2966; -- dev_dbg(&new_client->dev, "Using %s reference voltage\n", -+ dev_dbg(&client->dev, "Using %s reference voltage\n", - (i&0x02) ? "external" : "internal"); - - data->vid_conf = confreg[3]; -@@ -847,154 +932,64 @@ - if (devid == 0xe9 && data->address[1]) /* PC87366 */ - use_thermistors = confreg[2] & 0x40; - -- pc87360_init_client(new_client, use_thermistors); -+ pc87360_init_client(client, use_thermistors); - } - - /* Register sysfs hooks */ -- data->class_dev = hwmon_device_register(&new_client->dev); -+ data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); - goto ERROR3; - } - - if (data->innr) { -- device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr); -- -- device_create_file(&new_client->dev, &dev_attr_cpu0_vid); -- device_create_file(&new_client->dev, &dev_attr_vrm); -- device_create_file(&new_client->dev, &dev_attr_alarms_in); -+ for (i = 0; i < 11; i++) { -+ device_create_file(dev, &in_input[i].dev_attr); -+ device_create_file(dev, &in_min[i].dev_attr); -+ device_create_file(dev, &in_max[i].dev_attr); -+ device_create_file(dev, &in_status[i].dev_attr); -+ } -+ device_create_file(dev, &dev_attr_cpu0_vid); -+ device_create_file(dev, &dev_attr_vrm); -+ device_create_file(dev, &dev_attr_alarms_in); - } - - if (data->tempnr) { -- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr); -- -- device_create_file(&new_client->dev, &dev_attr_alarms_temp); -- } -- if (data->tempnr == 3) { -- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr); -+ for (i = 0; i < data->tempnr; i++) { -+ device_create_file(dev, &temp_input[i].dev_attr); -+ device_create_file(dev, &temp_min[i].dev_attr); -+ device_create_file(dev, &temp_max[i].dev_attr); -+ device_create_file(dev, &temp_crit[i].dev_attr); -+ device_create_file(dev, &temp_status[i].dev_attr); -+ } -+ device_create_file(dev, &dev_attr_alarms_temp); - } -+ - if (data->innr == 14) { -- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr); -- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr); -- } -- -- if (data->fannr) { -- if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) { -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan1_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan1_min.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan1_div.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan1_status.dev_attr); -- } -- -- if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) { -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan2_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan2_min.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan2_div.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan2_status.dev_attr); -- } -- -- if (FAN_CONFIG_CONTROL(data->fan_conf, 0)) -- device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr); -- if (FAN_CONFIG_CONTROL(data->fan_conf, 1)) -- device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr); -- } -- if (data->fannr == 3) { -- if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) { -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan3_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan3_min.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan3_div.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_fan3_status.dev_attr); -+ for (i = 0; i < 3; i++) { -+ device_create_file(dev, &therm_input[i].dev_attr); -+ device_create_file(dev, &therm_min[i].dev_attr); -+ device_create_file(dev, &therm_max[i].dev_attr); -+ device_create_file(dev, &therm_crit[i].dev_attr); -+ device_create_file(dev, &therm_status[i].dev_attr); - } -+ } - -- if (FAN_CONFIG_CONTROL(data->fan_conf, 2)) -- device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); -+ for (i = 0; i < data->fannr; i++) { -+ if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { -+ device_create_file(dev, &fan_input[i].dev_attr); -+ device_create_file(dev, &fan_min[i].dev_attr); -+ device_create_file(dev, &fan_div[i].dev_attr); -+ device_create_file(dev, &fan_status[i].dev_attr); -+ } -+ if (FAN_CONFIG_CONTROL(data->fan_conf, i)) -+ device_create_file(dev, &pwm[i].dev_attr); - } - - return 0; - - ERROR3: -- i2c_detach_client(new_client); -+ i2c_detach_client(client); - ERROR2: - for (i = 0; i < 3; i++) { - if (data->address[i]) { -@@ -1033,11 +1028,11 @@ - { - int res; - -- down(&(data->lock)); -+ mutex_lock(&(data->lock)); - if (bank != NO_BANK) - outb_p(bank, data->address[ldi] + PC87365_REG_BANK); - res = inb_p(data->address[ldi] + reg); -- up(&(data->lock)); -+ mutex_unlock(&(data->lock)); - - return res; - } -@@ -1045,11 +1040,11 @@ - static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, - u8 reg, u8 value) - { -- down(&(data->lock)); -+ mutex_lock(&(data->lock)); - if (bank != NO_BANK) - outb_p(bank, data->address[ldi] + PC87365_REG_BANK); - outb_p(value, data->address[ldi] + reg); -- up(&(data->lock)); -+ mutex_unlock(&(data->lock)); - } - - static void pc87360_init_client(struct i2c_client *client, int use_thermistors) -@@ -1071,7 +1066,7 @@ - } - - nr = data->innr < 11 ? data->innr : 11; -- for (i=0; i<nr; i++) { -+ for (i = 0; i < nr; i++) { - if (init >= init_in[i]) { - /* Forcibly enable voltage channel */ - reg = pc87360_read_value(data, LD_IN, i, -@@ -1088,14 +1083,14 @@ - - /* We can't blindly trust the Super-I/O space configuration bit, - most BIOS won't set it properly */ -- for (i=11; i<data->innr; i++) { -+ for (i = 11; i < data->innr; i++) { - reg = pc87360_read_value(data, LD_IN, i, - PC87365_REG_TEMP_STATUS); - use_thermistors = use_thermistors || (reg & 0x01); - } - - i = use_thermistors ? 2 : 0; -- for (; i<data->tempnr; i++) { -+ for (; i < data->tempnr; i++) { - if (init >= init_temp[i]) { - /* Forcibly enable temperature channel */ - reg = pc87360_read_value(data, LD_TEMP, i, -@@ -1111,7 +1106,7 @@ - } - - if (use_thermistors) { -- for (i=11; i<data->innr; i++) { -+ for (i = 11; i < data->innr; i++) { - if (init >= init_in[i]) { - /* The pin may already be used by thermal - diodes */ -@@ -1221,7 +1216,7 @@ - struct pc87360_data *data = i2c_get_clientdata(client); - u8 i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - dev_dbg(&client->dev, "Data update\n"); -@@ -1321,7 +1316,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/f71805f.c 2006-03-22 17:06:11.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/f71805f.c 2006-03-22 17:06:16.000000000 +0100 -@@ -30,6 +30,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-sysfs.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - static struct platform_device *pdev; -@@ -98,10 +99,6 @@ - #define ADDR_REG_OFFSET 0 - #define DATA_REG_OFFSET 1 - --static struct resource f71805f_resource __initdata = { -- .flags = IORESOURCE_IO, --}; -- - /* - * Registers - */ -@@ -131,10 +128,10 @@ - struct f71805f_data { - unsigned short addr; - const char *name; -- struct semaphore lock; -+ struct mutex lock; - struct class_device *class_dev; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned long last_limits; /* In jiffies */ -@@ -150,7 +147,7 @@ - u8 temp_high[3]; - u8 temp_hyst[3]; - u8 temp_mode; -- u8 alarms[3]; -+ unsigned long alarms; - }; - - static inline long in_from_reg(u8 reg) -@@ -224,20 +221,20 @@ - { - u8 val; - -- down(&data->lock); -+ mutex_lock(&data->lock); - outb(reg, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - - return val; - } - - static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) - { -- down(&data->lock); -+ mutex_lock(&data->lock); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val, data->addr + DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - } - - /* It is important to read the MSB first, because doing so latches the -@@ -246,24 +243,24 @@ - { - u16 val; - -- down(&data->lock); -+ mutex_lock(&data->lock); - outb(reg, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(++reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - - return val; - } - - static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) - { -- down(&data->lock); -+ mutex_lock(&data->lock); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(++reg, data->addr + ADDR_REG_OFFSET); - outb(val & 0xff, data->addr + DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - } - - static struct f71805f_data *f71805f_update_device(struct device *dev) -@@ -271,7 +268,7 @@ - struct f71805f_data *data = dev_get_drvdata(dev); - int nr; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - /* Limit registers cache is refreshed after 60 seconds */ - if (time_after(jiffies, data->last_updated + 60 * HZ) -@@ -314,16 +311,15 @@ - data->temp[nr] = f71805f_read8(data, - F71805F_REG_TEMP(nr)); - } -- for (nr = 0; nr < 3; nr++) { -- data->alarms[nr] = f71805f_read8(data, -- F71805F_REG_STATUS(nr)); -- } -+ data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0)) -+ + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8) -+ + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); - - data->last_updated = jiffies; - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } -@@ -362,10 +358,10 @@ - struct f71805f_data *data = dev_get_drvdata(dev); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_high[0] = in0_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -376,18 +372,14 @@ - struct f71805f_data *data = dev_get_drvdata(dev); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_low[0] = in0_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); --static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); --static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); -- - static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf) - { -@@ -426,10 +418,10 @@ - int nr = attr->index; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_high[nr] = in_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -442,31 +434,14 @@ - int nr = attr->index; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_low[nr] = in_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --#define sysfs_in(offset) \ --static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ -- show_in, NULL, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ -- show_in_max, set_in_max, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ -- show_in_min, set_in_min, offset) -- --sysfs_in(1); --sysfs_in(2); --sysfs_in(3); --sysfs_in(4); --sysfs_in(5); --sysfs_in(6); --sysfs_in(7); --sysfs_in(8); -- - static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) - { -@@ -495,24 +470,14 @@ - int nr = attr->index; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_low[nr] = fan_to_reg(val); - f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --#define sysfs_fan(offset) \ --static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ -- show_fan, NULL, offset - 1); \ --static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ -- show_fan_min, set_fan_min, offset - 1) -- --sysfs_fan(1); --sysfs_fan(2); --sysfs_fan(3); -- - static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) - { -@@ -562,10 +527,10 @@ - int nr = attr->index; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_high[nr] = temp_to_reg(val); - f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -578,35 +543,20 @@ - int nr = attr->index; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_hyst[nr] = temp_to_reg(val); - f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --#define sysfs_temp(offset) \ --static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ -- show_temp, NULL, offset - 1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ -- show_temp_max, set_temp_max, offset - 1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ -- show_temp_hyst, set_temp_hyst, offset - 1); \ --static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ -- show_temp_type, NULL, offset - 1) -- --sysfs_temp(1); --sysfs_temp(2); --sysfs_temp(3); -- - static ssize_t show_alarms_in(struct device *dev, struct device_attribute - *devattr, char *buf) - { - struct f71805f_data *data = f71805f_update_device(dev); - -- return sprintf(buf, "%d\n", data->alarms[0] | -- ((data->alarms[1] & 0x01) << 8)); -+ return sprintf(buf, "%lu\n", data->alarms & 0x1ff); - } - - static ssize_t show_alarms_fan(struct device *dev, struct device_attribute -@@ -614,7 +564,7 @@ - { - struct f71805f_data *data = f71805f_update_device(dev); - -- return sprintf(buf, "%d\n", data->alarms[2] & 0x07); -+ return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07); - } - - static ssize_t show_alarms_temp(struct device *dev, struct device_attribute -@@ -622,12 +572,18 @@ - { - struct f71805f_data *data = f71805f_update_device(dev); - -- return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); -+ return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07); - } - --static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); --static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); --static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); -+static ssize_t show_alarm(struct device *dev, struct device_attribute -+ *devattr, char *buf) -+{ -+ struct f71805f_data *data = f71805f_update_device(dev); -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ int nr = attr->index; -+ -+ return sprintf(buf, "%lu\n", (data->alarms >> nr) & 1); -+} - - static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -@@ -637,7 +593,104 @@ - return sprintf(buf, "%s\n", data->name); - } - --static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -+static struct device_attribute f71805f_dev_attr[] = { -+ __ATTR(in0_input, S_IRUGO, show_in0, NULL), -+ __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max), -+ __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min), -+ __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL), -+ __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL), -+ __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL), -+ __ATTR(name, S_IRUGO, show_name, NULL), -+}; -+ -+static struct sensor_device_attribute f71805f_sensor_attr[] = { -+ SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), -+ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), -+ SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 1), -+ SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 1), -+ SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), -+ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), -+ SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 2), -+ SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 2), -+ SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), -+ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), -+ SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 3), -+ SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 3), -+ SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), -+ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), -+ SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 4), -+ SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 4), -+ SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4), -+ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), -+ SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 5), -+ SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 5), -+ SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5), -+ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), -+ SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 6), -+ SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 6), -+ SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6), -+ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), -+ SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 7), -+ SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 7), -+ SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7), -+ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), -+ SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR, -+ show_in_max, set_in_max, 8), -+ SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR, -+ show_in_min, set_in_min, 8), -+ SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8), -+ -+ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), -+ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 0), -+ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, -+ show_temp_hyst, set_temp_hyst, 0), -+ SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), -+ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11), -+ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), -+ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 1), -+ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, -+ show_temp_hyst, set_temp_hyst, 1), -+ SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), -+ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12), -+ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), -+ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, -+ show_temp_max, set_temp_max, 2), -+ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, -+ show_temp_hyst, set_temp_hyst, 2), -+ SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), -+ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), -+}; -+ -+static struct sensor_device_attribute f71805f_fan_attr[] = { -+ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), -+ SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR, -+ show_fan_min, set_fan_min, 0), -+ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16), -+ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), -+ SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR, -+ show_fan_min, set_fan_min, 1), -+ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17), -+ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), -+ SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR, -+ show_fan_min, set_fan_min, 2), -+ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18), -+}; - - /* - * Device registration and initialization -@@ -668,7 +721,7 @@ - { - struct f71805f_data *data; - struct resource *res; -- int err; -+ int i, err; - - if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { - err = -ENOMEM; -@@ -678,9 +731,9 @@ - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - data->addr = res->start; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - data->name = "f71805f"; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - platform_set_drvdata(pdev, data); - -@@ -695,76 +748,31 @@ - f71805f_init_device(data); - - /* Register sysfs interface files */ -- device_create_file(&pdev->dev, &dev_attr_in0_input); -- device_create_file(&pdev->dev, &dev_attr_in0_max); -- device_create_file(&pdev->dev, &dev_attr_in0_min); -- device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); -- if (data->fan_enabled & (1 << 0)) { -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan1_input.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan1_min.dev_attr); -- } -- if (data->fan_enabled & (1 << 1)) { -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan2_input.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan2_min.dev_attr); -- } -- if (data->fan_enabled & (1 << 2)) { -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan3_input.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_fan3_min.dev_attr); -- } -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp1_input.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp2_input.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp3_input.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp1_max_hyst.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp2_max_hyst.dev_attr); -- device_create_file(&pdev->dev, -- &sensor_dev_attr_temp3_max_hyst.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); -- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); -- device_create_file(&pdev->dev, &dev_attr_alarms_in); -- device_create_file(&pdev->dev, &dev_attr_alarms_fan); -- device_create_file(&pdev->dev, &dev_attr_alarms_temp); -- device_create_file(&pdev->dev, &dev_attr_name); -+ for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) { -+ err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]); -+ if (err) -+ goto exit_class; -+ } -+ for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) { -+ err = device_create_file(&pdev->dev, -+ &f71805f_sensor_attr[i].dev_attr); -+ if (err) -+ goto exit_class; -+ } -+ for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) { -+ if (!(data->fan_enabled & (1 << (i / 3)))) -+ continue; -+ err = device_create_file(&pdev->dev, -+ &f71805f_fan_attr[i].dev_attr); -+ if (err) -+ goto exit_class; -+ } - - return 0; - -+exit_class: -+ dev_err(&pdev->dev, "Sysfs interface creation failed\n"); -+ hwmon_device_unregister(data->class_dev); - exit_free: - kfree(data); - exit: -@@ -793,6 +801,11 @@ - - static int __init f71805f_device_add(unsigned short address) - { -+ struct resource res = { -+ .start = address, -+ .end = address + REGION_LENGTH - 1, -+ .flags = IORESOURCE_IO, -+ }; - int err; - - pdev = platform_device_alloc(DRVNAME, address); -@@ -802,10 +815,8 @@ - goto exit; - } - -- f71805f_resource.start = address; -- f71805f_resource.end = address + REGION_LENGTH - 1; -- f71805f_resource.name = pdev->name; -- err = platform_device_add_resources(pdev, &f71805f_resource, 1); -+ res.name = pdev->name; -+ err = platform_device_add_resources(pdev, &res, 1); - if (err) { - printk(KERN_ERR DRVNAME ": Device resource addition failed " - "(%d)\n", err); ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali1535.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ali1535.c 2006-03-22 17:06:16.000000000 +0100 -@@ -63,7 +63,6 @@ - #include <linux/i2c.h> - #include <linux/init.h> - #include <asm/io.h> --#include <asm/semaphore.h> - - - /* ALI1535 SMBus address offsets */ -@@ -136,7 +135,6 @@ - - static struct pci_driver ali1535_driver; - static unsigned short ali1535_smba; --static DECLARE_MUTEX(i2c_ali1535_sem); - - /* Detect whether a ALI1535 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and -@@ -345,7 +343,6 @@ - int timeout; - s32 result = 0; - -- down(&i2c_ali1535_sem); - /* make sure SMBus is idle */ - temp = inb_p(SMBHSTSTS); - for (timeout = 0; -@@ -460,7 +457,6 @@ - break; - } - EXIT: -- up(&i2c_ali1535_sem); - return result; - } - -@@ -479,7 +475,7 @@ - - static struct i2c_adapter ali1535_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/chips/ds1374.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/ds1374.c 2006-03-22 17:06:14.000000000 +0100 -@@ -26,6 +26,7 @@ - #include <linux/i2c.h> - #include <linux/rtc.h> - #include <linux/bcd.h> -+#include <linux/mutex.h> - - #define DS1374_REG_TOD0 0x00 - #define DS1374_REG_TOD1 0x01 -@@ -41,7 +42,7 @@ - - #define DS1374_DRV_NAME "ds1374" - --static DECLARE_MUTEX(ds1374_mutex); -+static DEFINE_MUTEX(ds1374_mutex); - - static struct i2c_driver ds1374_driver; - static struct i2c_client *save_client; -@@ -114,7 +115,7 @@ - ulong t1, t2; - int limit = 10; /* arbitrary retry limit */ - -- down(&ds1374_mutex); -+ mutex_lock(&ds1374_mutex); - - /* - * Since the reads are being performed one byte at a time using -@@ -127,7 +128,7 @@ - t2 = ds1374_read_rtc(); - } while (t1 != t2 && limit--); - -- up(&ds1374_mutex); -+ mutex_unlock(&ds1374_mutex); - - if (t1 != t2) { - dev_warn(&save_client->dev, -@@ -145,7 +146,7 @@ - - t1 = *(ulong *) arg; - -- down(&ds1374_mutex); -+ mutex_lock(&ds1374_mutex); - - /* - * Since the writes are being performed one byte at a time using -@@ -158,7 +159,7 @@ - t2 = ds1374_read_rtc(); - } while (t1 != t2 && limit--); - -- up(&ds1374_mutex); -+ mutex_unlock(&ds1374_mutex); - - if (t1 != t2) - dev_warn(&save_client->dev, ---- linux-2.6.16.orig/drivers/i2c/chips/m41t00.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/m41t00.c 2006-03-22 17:06:14.000000000 +0100 -@@ -24,13 +24,14 @@ - #include <linux/i2c.h> - #include <linux/rtc.h> - #include <linux/bcd.h> -+#include <linux/mutex.h> - - #include <asm/time.h> - #include <asm/rtc.h> - - #define M41T00_DRV_NAME "m41t00" - --static DECLARE_MUTEX(m41t00_mutex); -+static DEFINE_MUTEX(m41t00_mutex); - - static struct i2c_driver m41t00_driver; - static struct i2c_client *save_client; -@@ -54,7 +55,7 @@ - sec = min = hour = day = mon = year = 0; - sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - -- down(&m41t00_mutex); -+ mutex_lock(&m41t00_mutex); - do { - if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) - && ((min = i2c_smbus_read_byte_data(save_client, 1)) -@@ -80,7 +81,7 @@ - mon1 = mon; - year1 = year; - } while (--limit > 0); -- up(&m41t00_mutex); -+ mutex_unlock(&m41t00_mutex); - - if (limit == 0) { - dev_warn(&save_client->dev, -@@ -125,7 +126,7 @@ - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - -- down(&m41t00_mutex); -+ mutex_lock(&m41t00_mutex); - if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) - || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) - < 0) -@@ -140,7 +141,7 @@ - - dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - -- up(&m41t00_mutex); -+ mutex_unlock(&m41t00_mutex); - return; - } - ---- linux-2.6.16.orig/drivers/i2c/i2c-core.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/i2c-core.c 2006-03-22 17:06:21.000000000 +0100 -@@ -31,14 +31,17 @@ - #include <linux/idr.h> - #include <linux/seq_file.h> - #include <linux/platform_device.h> -+#include <linux/mutex.h> - #include <asm/uaccess.h> - - - static LIST_HEAD(adapters); - static LIST_HEAD(drivers); --static DECLARE_MUTEX(core_lists); -+static DEFINE_MUTEX(core_lists); - static DEFINE_IDR(i2c_adapter_idr); - -+static void i2c_notify(struct i2c_adapter *adap, struct i2c_driver *driver); -+ - /* 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) - { -@@ -153,7 +156,7 @@ - struct list_head *item; - struct i2c_driver *driver; - -- down(&core_lists); -+ mutex_lock(&core_lists); - - if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { - res = -ENOMEM; -@@ -168,8 +171,8 @@ - } - - adap->nr = id & MAX_ID_MASK; -- init_MUTEX(&adap->bus_lock); -- init_MUTEX(&adap->clist_lock); -+ mutex_init(&adap->bus_lock); -+ mutex_init(&adap->clist_lock); - list_add_tail(&adap->list,&adapters); - INIT_LIST_HEAD(&adap->clients); - -@@ -197,13 +200,11 @@ - /* inform drivers of new adapters */ - list_for_each(item,&drivers) { - driver = list_entry(item, struct i2c_driver, list); -- if (driver->attach_adapter) -- /* We ignore the return code; if it fails, too bad */ -- driver->attach_adapter(adap); -+ i2c_notify(adap, driver); - } - - out_unlock: -- up(&core_lists); -+ mutex_unlock(&core_lists); - return res; - } - -@@ -216,7 +217,7 @@ - struct i2c_client *client; - int res = 0; - -- down(&core_lists); -+ mutex_lock(&core_lists); - - /* First make sure that this adapter was ever added */ - list_for_each_entry(adap_from_list, &adapters, list) { -@@ -272,7 +273,7 @@ - dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - - out_unlock: -- up(&core_lists); -+ mutex_unlock(&core_lists); - return res; - } - -@@ -287,9 +288,7 @@ - { - struct list_head *item; - struct i2c_adapter *adapter; -- int res = 0; -- -- down(&core_lists); -+ int res; - - /* add the driver to the list of i2c drivers in the driver core */ - driver->driver.owner = owner; -@@ -297,22 +296,21 @@ - - res = driver_register(&driver->driver); - if (res) -- goto out_unlock; -+ return res; - -+ mutex_lock(&core_lists); -+ - list_add_tail(&driver->list,&drivers); - pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - - /* now look for instances of driver on our adapters */ -- if (driver->attach_adapter) { -- list_for_each(item,&adapters) { -- adapter = list_entry(item, struct i2c_adapter, list); -- driver->attach_adapter(adapter); -- } -+ list_for_each(item, &adapters) { -+ adapter = list_entry(item, struct i2c_adapter, list); -+ i2c_notify(adapter, driver); - } - -- out_unlock: -- up(&core_lists); -- return res; -+ mutex_unlock(&core_lists); -+ return 0; - } - EXPORT_SYMBOL(i2c_register_driver); - -@@ -324,7 +322,7 @@ - - int res = 0; - -- down(&core_lists); -+ mutex_lock(&core_lists); - - /* Have a look at each adapter, if clients of this driver are still - * attached. If so, detach them to be able to kill the driver -@@ -363,7 +361,7 @@ - pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); - - out_unlock: -- up(&core_lists); -+ mutex_unlock(&core_lists); - return 0; - } - -@@ -384,9 +382,9 @@ - { - int rval; - -- down(&adapter->clist_lock); -+ mutex_lock(&adapter->clist_lock); - rval = __i2c_check_addr(adapter, addr); -- up(&adapter->clist_lock); -+ mutex_unlock(&adapter->clist_lock); - - return rval; - } -@@ -395,13 +393,13 @@ - { - struct i2c_adapter *adapter = client->adapter; - -- down(&adapter->clist_lock); -+ mutex_lock(&adapter->clist_lock); - if (__i2c_check_addr(client->adapter, client->addr)) { -- up(&adapter->clist_lock); -+ mutex_unlock(&adapter->clist_lock); - return -EBUSY; - } - list_add_tail(&client->list,&adapter->clients); -- up(&adapter->clist_lock); -+ mutex_unlock(&adapter->clist_lock); - - if (adapter->client_register) { - if (adapter->client_register(client)) { -@@ -450,12 +448,12 @@ - } - } - -- down(&adapter->clist_lock); -+ mutex_lock(&adapter->clist_lock); - list_del(&client->list); - init_completion(&client->released); - device_remove_file(&client->dev, &dev_attr_client_name); - device_unregister(&client->dev); -- up(&adapter->clist_lock); -+ mutex_unlock(&adapter->clist_lock); - wait_for_completion(&client->released); - - out: -@@ -513,19 +511,19 @@ - struct list_head *item; - struct i2c_client *client; - -- down(&adap->clist_lock); -+ mutex_lock(&adap->clist_lock); - list_for_each(item,&adap->clients) { - client = list_entry(item, struct i2c_client, list); - if (!try_module_get(client->driver->driver.owner)) - continue; - if (NULL != client->driver->command) { -- up(&adap->clist_lock); -+ mutex_unlock(&adap->clist_lock); - client->driver->command(client,cmd,arg); -- down(&adap->clist_lock); -+ mutex_lock(&adap->clist_lock); - } - module_put(client->driver->driver.owner); - } -- up(&adap->clist_lock); -+ mutex_unlock(&adap->clist_lock); - } - - static int __init i2c_init(void) -@@ -569,9 +567,9 @@ - } - #endif - -- down(&adap->bus_lock); -+ mutex_lock(&adap->bus_lock); - ret = adap->algo->master_xfer(adap,msgs,num); -- up(&adap->bus_lock); -+ mutex_unlock(&adap->bus_lock); - - return ret; - } else { -@@ -775,16 +773,53 @@ - return 0; - } - -+/* For explicitely attaching a driver to a given device */ -+int i2c_probe_device(struct i2c_adapter *adapter, int driver_id, -+ int addr, int kind) -+{ -+ struct list_head *item; -+ struct i2c_driver *driver = NULL; -+ -+ /* There's no way to probe addresses on this adapter... */ -+ if (kind < 0 && !i2c_check_functionality(adapter, -+ I2C_FUNC_SMBUS_QUICK)) -+ return -EINVAL; -+ -+ mutex_lock(&core_lists); -+ list_for_each(item, &drivers) { -+ driver = list_entry(item, struct i2c_driver, list); -+ if (driver->id == driver_id) -+ break; -+ } -+ mutex_unlock(&core_lists); -+ if (!item) -+ return -ENOENT; -+ -+ return i2c_probe_address(adapter, addr, kind, driver->detect_client); -+} -+ -+static void i2c_notify(struct i2c_adapter *adap, struct i2c_driver *driver) -+{ -+ if (driver->attach_adapter) -+ driver->attach_adapter(adap); -+ -+ /* Probe devices if the driver provided the necessary information -+ (detect_client and address_data) */ -+ if (driver->detect_client && driver->address_data && -+ (driver->class & adap->class)) -+ i2c_probe(adap, driver->address_data, driver->detect_client); -+} -+ - struct i2c_adapter* i2c_get_adapter(int id) - { - struct i2c_adapter *adapter; - -- down(&core_lists); -+ mutex_lock(&core_lists); - adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); - if (adapter && !try_module_get(adapter->owner)) - adapter = NULL; - -- up(&core_lists); -+ mutex_unlock(&core_lists); - return adapter; - } - -@@ -919,12 +954,11 @@ - u8 length, u8 *values) - { - union i2c_smbus_data data; -- int i; -+ - if (length > I2C_SMBUS_BLOCK_MAX) - length = I2C_SMBUS_BLOCK_MAX; -- for (i = 1; i <= length; i++) -- data.block[i] = values[i-1]; - data.block[0] = length; -+ memcpy(&data.block[1], values, length); - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_WRITE,command, - I2C_SMBUS_BLOCK_DATA,&data); -@@ -934,16 +968,14 @@ - s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) - { - union i2c_smbus_data data; -- int i; -+ - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, - I2C_SMBUS_I2C_BLOCK_DATA,&data)) - return -1; -- else { -- for (i = 1; i <= data.block[0]; i++) -- values[i-1] = data.block[i]; -- return data.block[0]; -- } -+ -+ memcpy(values, &data.block[1], data.block[0]); -+ return data.block[0]; - } - - s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, -@@ -1118,10 +1150,10 @@ - flags &= I2C_M_TEN | I2C_CLIENT_PEC; - - if (adapter->algo->smbus_xfer) { -- down(&adapter->bus_lock); -+ mutex_lock(&adapter->bus_lock); - res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, - command,size,data); -- up(&adapter->bus_lock); -+ mutex_unlock(&adapter->bus_lock); - } else - res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, - command,size,data); -@@ -1153,6 +1185,7 @@ - EXPORT_SYMBOL(i2c_get_adapter); - EXPORT_SYMBOL(i2c_put_adapter); - EXPORT_SYMBOL(i2c_probe); -+EXPORT_SYMBOL(i2c_probe_device); - - EXPORT_SYMBOL(i2c_smbus_xfer); - EXPORT_SYMBOL(i2c_smbus_write_quick); ---- linux-2.6.16.orig/drivers/i2c/busses/scx200_acb.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/scx200_acb.c 2006-03-22 17:06:16.000000000 +0100 -@@ -1,27 +1,26 @@ --/* linux/drivers/i2c/scx200_acb.c -- -+/* - Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> - - National Semiconductor SCx200 ACCESS.bus support -- -+ Also supports the AMD CS5535 and AMD CS5536 -+ - Based on i2c-keywest.c which is: - Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> - Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> -- -+ - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. -- -+ - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. -- -+ - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- - */ - - #include <linux/module.h> -@@ -32,7 +31,9 @@ - #include <linux/smp_lock.h> - #include <linux/pci.h> - #include <linux/delay.h> -+#include <linux/mutex.h> - #include <asm/io.h> -+#include <asm/msr.h> - - #include <linux/scx200.h> - -@@ -47,16 +48,7 @@ - module_param_array(base, int, NULL, 0); - MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); - --#ifdef DEBUG --#define DBG(x...) printk(KERN_DEBUG NAME ": " x) --#else --#define DBG(x...) --#endif -- --/* The hardware supports interrupt driven mode too, but I haven't -- implemented that. */ --#define POLLED_MODE 1 --#define POLL_TIMEOUT (HZ) -+#define POLL_TIMEOUT (HZ/5) - - enum scx200_acb_state { - state_idle, -@@ -79,12 +71,11 @@ - }; - - /* Physical interface */ --struct scx200_acb_iface --{ -+struct scx200_acb_iface { - struct scx200_acb_iface *next; - struct i2c_adapter adapter; - unsigned base; -- struct semaphore sem; -+ struct mutex mutex; - - /* State machine data */ - enum scx200_acb_state state; -@@ -100,7 +91,7 @@ - #define ACBSDA (iface->base + 0) - #define ACBST (iface->base + 1) - #define ACBST_SDAST 0x40 /* SDA Status */ --#define ACBST_BER 0x20 -+#define ACBST_BER 0x20 - #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ - #define ACBST_STASTR 0x08 /* Stall After Start */ - #define ACBST_MASTER 0x02 -@@ -109,9 +100,9 @@ - #define ACBCTL1 (iface->base + 3) - #define ACBCTL1_STASTRE 0x80 - #define ACBCTL1_NMINTE 0x40 --#define ACBCTL1_ACK 0x10 --#define ACBCTL1_STOP 0x02 --#define ACBCTL1_START 0x01 -+#define ACBCTL1_ACK 0x10 -+#define ACBCTL1_STOP 0x02 -+#define ACBCTL1_START 0x01 - #define ACBADDR (iface->base + 4) - #define ACBCTL2 (iface->base + 5) - #define ACBCTL2_ENABLE 0x01 -@@ -122,8 +113,8 @@ - { - const char *errmsg; - -- DBG("state %s, status = 0x%02x\n", -- scx200_acb_state_name[iface->state], status); -+ dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", -+ scx200_acb_state_name[iface->state], status); - - if (status & ACBST_BER) { - errmsg = "bus error"; -@@ -133,8 +124,17 @@ - errmsg = "not master"; - goto error; - } -- if (status & ACBST_NEGACK) -- goto negack; -+ if (status & ACBST_NEGACK) { -+ dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", -+ scx200_acb_state_name[iface->state]); -+ -+ iface->state = state_idle; -+ iface->result = -ENXIO; -+ -+ outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); -+ outb(ACBST_STASTR | ACBST_NEGACK, ACBST); -+ return; -+ } - - switch (iface->state) { - case state_idle: -@@ -160,10 +160,10 @@ - case state_repeat_start: - outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); - /* fallthrough */ -- -+ - case state_quick: - if (iface->address_byte & 1) { -- if (iface->len == 1) -+ if (iface->len == 1) - outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); - else - outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); -@@ -202,26 +202,15 @@ - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - break; - } -- -+ - outb(*iface->ptr++, ACBSDA); - --iface->len; -- -+ - break; - } - - return; - -- negack: -- DBG("negative acknowledge in state %s\n", -- scx200_acb_state_name[iface->state]); -- -- iface->state = state_idle; -- iface->result = -ENXIO; -- -- outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); -- outb(ACBST_STASTR | ACBST_NEGACK, ACBST); -- return; -- - error: - dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, - scx200_acb_state_name[iface->state]); -@@ -231,20 +220,9 @@ - iface->needs_reset = 1; - } - --static void scx200_acb_timeout(struct scx200_acb_iface *iface) --{ -- dev_err(&iface->adapter.dev, "timeout in state %s\n", -- scx200_acb_state_name[iface->state]); -- -- iface->state = state_idle; -- iface->result = -EIO; -- iface->needs_reset = 1; --} -- --#ifdef POLLED_MODE - static void scx200_acb_poll(struct scx200_acb_iface *iface) - { -- u8 status = 0; -+ u8 status; - unsigned long timeout; - - timeout = jiffies + POLL_TIMEOUT; -@@ -254,17 +232,21 @@ - scx200_acb_machine(iface, status); - return; - } -- msleep(10); -+ yield(); - } - -- scx200_acb_timeout(iface); -+ dev_err(&iface->adapter.dev, "timeout in state %s\n", -+ scx200_acb_state_name[iface->state]); -+ -+ iface->state = state_idle; -+ iface->result = -EIO; -+ iface->needs_reset = 1; - } --#endif /* POLLED_MODE */ - - static void scx200_acb_reset(struct scx200_acb_iface *iface) - { - /* Disable the ACCESS.bus device and Configure the SCL -- frequency: 16 clock cycles */ -+ frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - /* Polling mode */ - outb(0, ACBCTL1); -@@ -283,9 +265,9 @@ - } - - static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, -- u16 address, unsigned short flags, -- char rw, u8 command, int size, -- union i2c_smbus_data *data) -+ u16 address, unsigned short flags, -+ char rw, u8 command, int size, -+ union i2c_smbus_data *data) - { - struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); - int len; -@@ -295,53 +277,47 @@ - - switch (size) { - case I2C_SMBUS_QUICK: -- len = 0; -- buffer = NULL; -- break; -+ len = 0; -+ buffer = NULL; -+ break; -+ - case I2C_SMBUS_BYTE: -- if (rw == I2C_SMBUS_READ) { -- len = 1; -- buffer = &data->byte; -- } else { -- len = 1; -- buffer = &command; -- } -- break; -+ len = 1; -+ buffer = rw ? &data->byte : &command; -+ break; -+ - case I2C_SMBUS_BYTE_DATA: -- len = 1; -- buffer = &data->byte; -- break; -+ len = 1; -+ buffer = &data->byte; -+ break; -+ - case I2C_SMBUS_WORD_DATA: - len = 2; -- cur_word = cpu_to_le16(data->word); -- buffer = (u8 *)&cur_word; -+ cur_word = cpu_to_le16(data->word); -+ buffer = (u8 *)&cur_word; - break; -+ - case I2C_SMBUS_BLOCK_DATA: -- len = data->block[0]; -- buffer = &data->block[1]; -+ len = data->block[0]; -+ buffer = &data->block[1]; - break; -+ - default: -- return -EINVAL; -+ return -EINVAL; - } - -- DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", -- size, address, command, len, rw == I2C_SMBUS_READ); -+ dev_dbg(&adapter->dev, -+ "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", -+ size, address, command, len, rw); - - if (!len && rw == I2C_SMBUS_READ) { -- dev_warn(&adapter->dev, "zero length read\n"); -+ dev_dbg(&adapter->dev, "zero length read\n"); - return -EINVAL; - } - -- if (len && !buffer) { -- dev_warn(&adapter->dev, "nonzero length but no buffer\n"); -- return -EFAULT; -- } -- -- down(&iface->sem); -+ mutex_lock(&iface->mutex); - -- iface->address_byte = address<<1; -- if (rw == I2C_SMBUS_READ) -- iface->address_byte |= 1; -+ iface->address_byte = (address << 1) | rw; - iface->command = command; - iface->ptr = buffer; - iface->len = len; -@@ -355,25 +331,21 @@ - else - iface->state = state_address; - --#ifdef POLLED_MODE - while (iface->state != state_idle) - scx200_acb_poll(iface); --#else /* POLLED_MODE */ --#error Interrupt driven mode not implemented --#endif /* POLLED_MODE */ - - if (iface->needs_reset) - scx200_acb_reset(iface); - - rc = iface->result; - -- up(&iface->sem); -+ mutex_unlock(&iface->mutex); - - if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) -- data->word = le16_to_cpu(cur_word); -+ data->word = le16_to_cpu(cur_word); - - #ifdef DEBUG -- DBG(": transfer done, result: %d", rc); -+ dev_dbg(&adapter->dev, "transfer done, result: %d", rc); - if (buffer) { - int i; - printk(" data:"); -@@ -400,17 +372,18 @@ - }; - - static struct scx200_acb_iface *scx200_acb_list; -+static DECLARE_MUTEX(scx200_acb_list_mutex); - - static int scx200_acb_probe(struct scx200_acb_iface *iface) - { - u8 val; - - /* Disable the ACCESS.bus device and Configure the SCL -- frequency: 16 clock cycles */ -+ frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - - if (inb(ACBCTL2) != 0x70) { -- DBG("ACBCTL2 readback failed\n"); -+ pr_debug(NAME ": ACBCTL2 readback failed\n"); - return -ENXIO; - } - -@@ -418,7 +391,8 @@ - - val = inb(ACBCTL1); - if (val) { -- DBG("disabled, but ACBCTL1=0x%02x\n", val); -+ pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", -+ val); - return -ENXIO; - } - -@@ -428,18 +402,19 @@ - - val = inb(ACBCTL1); - if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { -- DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); -+ pr_debug(NAME ": enabled, but NMINTE won't be set, " -+ "ACBCTL1=0x%02x\n", val); - return -ENXIO; - } - - return 0; - } - --static int __init scx200_acb_create(int base, int index) -+static int __init scx200_acb_create(const char *text, int base, int index) - { - struct scx200_acb_iface *iface; - struct i2c_adapter *adapter; -- int rc = 0; -+ int rc; - char description[64]; - - iface = kzalloc(sizeof(*iface), GFP_KERNEL); -@@ -451,50 +426,51 @@ - - adapter = &iface->adapter; - i2c_set_adapdata(adapter, iface); -- snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); -+ snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); - adapter->owner = THIS_MODULE; - adapter->id = I2C_HW_SMBUS_SCX200; - adapter->algo = &scx200_acb_algorithm; -- adapter->class = I2C_CLASS_HWMON; -+ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_DATA; -+ -+ mutex_init(&iface->mutex); - -- init_MUTEX(&iface->sem); -+ snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", -+ text, adapter->name); - -- snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); - if (request_region(base, 8, description) == 0) { -- dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", -+ printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", - base, base + 8-1); - rc = -EBUSY; -- goto errout; -+ goto errout_free; - } - iface->base = base; - - rc = scx200_acb_probe(iface); - if (rc) { -- dev_warn(&adapter->dev, "probe failed\n"); -- goto errout; -+ printk(KERN_WARNING NAME ": probe failed\n"); -+ goto errout_release; - } - - scx200_acb_reset(iface); - - if (i2c_add_adapter(adapter) < 0) { -- dev_err(&adapter->dev, "failed to register\n"); -+ printk(KERN_ERR NAME ": failed to register\n"); - rc = -ENODEV; -- goto errout; -+ goto errout_release; - } - -- lock_kernel(); -+ down(&scx200_acb_list_mutex); - iface->next = scx200_acb_list; - scx200_acb_list = iface; -- unlock_kernel(); -+ up(&scx200_acb_list_mutex); - - return 0; - -+ errout_release: -+ release_region(iface->base, 8); -+ errout_free: -+ kfree(iface); - errout: -- if (iface) { -- if (iface->base) -- release_region(iface->base, 8); -- kfree(iface); -- } - return rc; - } - -@@ -504,50 +480,69 @@ - { }, - }; - -+static struct pci_device_id divil_pci[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, -+ { } /* NULL entry */ -+}; -+ -+#define MSR_LBAR_SMB 0x5140000B -+ -+static int scx200_add_cs553x(void) -+{ -+ u32 low, hi; -+ u32 smb_base; -+ -+ /* Grab & reserve the SMB I/O range */ -+ rdmsr(MSR_LBAR_SMB, low, hi); -+ -+ /* Check the IO mask and whether SMB is enabled */ -+ if (hi != 0x0000F001) { -+ printk(KERN_WARNING NAME ": SMBus not enabled\n"); -+ return -ENODEV; -+ } -+ -+ /* SMBus IO size is 8 bytes */ -+ smb_base = low & 0x0000FFF8; -+ -+ return scx200_acb_create("CS5535", smb_base, 0); -+} -+ - static int __init scx200_acb_init(void) - { - int i; -- int rc; -+ int rc = -ENODEV; - - pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); - - /* Verify that this really is a SCx200 processor */ -- if (pci_dev_present(scx200) == 0) -- return -ENODEV; -+ if (pci_dev_present(scx200)) { -+ for (i = 0; i < MAX_DEVICES; ++i) { -+ if (base[i] > 0) -+ rc = scx200_acb_create("SCx200", base[i], i); -+ } -+ } else if (pci_dev_present(divil_pci)) -+ rc = scx200_add_cs553x(); - -- rc = -ENXIO; -- for (i = 0; i < MAX_DEVICES; ++i) { -- if (base[i] > 0) -- rc = scx200_acb_create(base[i], i); -- } -- if (scx200_acb_list) -- return 0; - return rc; - } - - static void __exit scx200_acb_cleanup(void) - { - struct scx200_acb_iface *iface; -- lock_kernel(); -+ -+ down(&scx200_acb_list_mutex); - while ((iface = scx200_acb_list) != NULL) { - scx200_acb_list = iface->next; -- unlock_kernel(); -+ up(&scx200_acb_list_mutex); - - i2c_del_adapter(&iface->adapter); - release_region(iface->base, 8); - kfree(iface); -- lock_kernel(); -+ down(&scx200_acb_list_mutex); - } -- unlock_kernel(); -+ up(&scx200_acb_list_mutex); - } - - module_init(scx200_acb_init); - module_exit(scx200_acb_cleanup); -- --/* -- Local variables: -- compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" -- c-basic-offset: 8 -- End: --*/ -- ---- linux-2.6.16.orig/Documentation/i2c/busses/scx200_acb 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/Documentation/i2c/busses/scx200_acb 2006-03-22 17:06:15.000000000 +0100 -@@ -6,9 +6,10 @@ - ----------------- - - * base: int -- Base addresses for the ACCESS.bus controllers -+ Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices - - Description - ----------- - --Enable the use of the ACCESS.bus controllers of a SCx200 processor. -+Enable the use of the ACCESS.bus controller on the Geode SCx200 and -+SC1100 processors and the CS5535 and CS5536 Geode companion devices. ---- linux-2.6.16.orig/drivers/i2c/busses/Kconfig 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/Kconfig 2006-03-22 17:06:16.000000000 +0100 -@@ -163,17 +163,22 @@ - I2C bus. - - config I2C_PIIX4 -- tristate "Intel PIIX4" -+ tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" - depends on I2C && PCI - help - If you say yes to this option, support will be included for the Intel - PIIX4 family of mainboard I2C interfaces. Specifically, the following -- versions of the chipset are supported: -+ versions of the chipset are supported (note that Serverworks is part -+ of Broadcom): - Intel PIIX4 - Intel 440MX -+ ATI IXP200 -+ ATI IXP300 -+ ATI IXP400 - Serverworks OSB4 - Serverworks CSB5 - Serverworks CSB6 -+ Serverworks HT-1000 - SMSC Victory66 - - This driver can also be built as a module. If so, the module -@@ -284,7 +289,10 @@ - This driver is a replacement for (and was inspired by) an older - driver named i2c-philips-par. The new driver supports more devices, - and makes it easier to add support for new devices. -- -+ -+ An adapter type parameter is now mandatory. Please read the file -+ Documentation/i2c/busses/i2c-parport for details. -+ - Another driver exists, named i2c-parport-light, which doesn't depend - on the parport driver. This is meant for embedded systems. Don't say - Y here if you intend to say Y or M there. -@@ -389,10 +397,11 @@ - also be specified with a module parameter. - - config SCx200_ACB -- tristate "NatSemi SCx200 ACCESS.bus" -- depends on I2C && PCI -+ tristate "Geode ACCESS.bus support" -+ depends on X86_32 && I2C && PCI - help -- Enable the use of the ACCESS.bus controllers of a SCx200 processor. -+ Enable the use of the ACCESS.bus controllers on the Geode SCx200 and -+ SC1100 processors and the CS5535 and CS5536 Geode companion devices. - - If you don't know what to do here, say N. - ---- linux-2.6.16.orig/drivers/hwmon/w83792d.c 2006-03-22 17:06:10.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/w83792d.c 2006-03-22 17:06:16.000000000 +0100 -@@ -43,6 +43,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-sysfs.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; -@@ -271,7 +272,7 @@ - struct class_device *class_dev; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -300,7 +301,6 @@ - u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ - }; - --static int w83792d_attach_adapter(struct i2c_adapter *adapter); - static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); - static int w83792d_detach_client(struct i2c_client *client); - static struct w83792d_data *w83792d_update_device(struct device *dev); -@@ -315,7 +315,9 @@ - .driver = { - .name = "w83792d", - }, -- .attach_adapter = w83792d_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = w83792d_detect, - .detach_client = w83792d_detach_client, - }; - -@@ -382,30 +384,40 @@ - store_in_reg(MIN, min); - store_in_reg(MAX, max); - --#define sysfs_in_reg(offset) \ --static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ -- NULL, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ -- show_in_min, store_in_min, offset); \ --static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ -- show_in_max, store_in_max, offset); -- --sysfs_in_reg(0); --sysfs_in_reg(1); --sysfs_in_reg(2); --sysfs_in_reg(3); --sysfs_in_reg(4); --sysfs_in_reg(5); --sysfs_in_reg(6); --sysfs_in_reg(7); --sysfs_in_reg(8); -- --#define device_create_file_in(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \ --} while (0) -+static struct sensor_device_attribute sda_in_input[] = { -+ SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), -+ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), -+ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), -+ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), -+ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), -+ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), -+ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), -+ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), -+ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), -+}; -+static struct sensor_device_attribute sda_in_min[] = { -+ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), -+ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), -+ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), -+ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), -+ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), -+ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), -+ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), -+ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), -+ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), -+}; -+static struct sensor_device_attribute sda_in_max[] = { -+ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), -+ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), -+ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), -+ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), -+ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), -+ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), -+ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), -+ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), -+ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), -+}; -+ - - #define show_fan_reg(reg) \ - static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ -@@ -486,28 +498,33 @@ - return count; - } - --#define sysfs_fan(offset) \ --static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ -- offset); \ --static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ -- show_fan_div, store_fan_div, offset); \ --static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ -- show_fan_min, store_fan_min, offset); -- --sysfs_fan(1); --sysfs_fan(2); --sysfs_fan(3); --sysfs_fan(4); --sysfs_fan(5); --sysfs_fan(6); --sysfs_fan(7); -- --#define device_create_file_fan(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ --} while (0) -+static struct sensor_device_attribute sda_fan_input[] = { -+ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1), -+ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2), -+ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3), -+ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4), -+ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5), -+ SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6), -+ SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7), -+}; -+static struct sensor_device_attribute sda_fan_min[] = { -+ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), -+ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), -+ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), -+ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4), -+ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5), -+ SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6), -+ SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7), -+}; -+static struct sensor_device_attribute sda_fan_div[] = { -+ SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), -+ SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), -+ SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), -+ SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4), -+ SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5), -+ SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6), -+ SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7), -+}; - - - /* read/write the temperature1, includes measured value and limits */ -@@ -539,21 +556,6 @@ - return count; - } - -- --static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0); --static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1, -- store_temp1, 1); --static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, -- store_temp1, 2); -- --#define device_create_file_temp1(client) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \ --} while (0) -- -- - /* read/write the temperature2-3, includes measured value and limits */ - - static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, -@@ -590,25 +592,23 @@ - return count; - } - --#define sysfs_temp23(name,idx) \ --static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ -- idx, 0); \ --static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ -- show_temp23, store_temp23, idx, 2); \ --static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \ -- show_temp23, store_temp23, idx, 4); -- --sysfs_temp23(temp2,0) --sysfs_temp23(temp3,1) -- --#define device_create_file_temp_add(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \ --device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \ --device_create_file(&client->dev, \ --&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \ --} while (0) -+static struct sensor_device_attribute_2 sda_temp_input[] = { -+ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), -+ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), -+ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), -+}; -+ -+static struct sensor_device_attribute_2 sda_temp_max[] = { -+ SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1), -+ SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2), -+ SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2), -+}; - -+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { -+ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2), -+ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4), -+ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4), -+}; - - /* get reatime status of all sensors items: voltage, temp, fan */ - static ssize_t -@@ -620,10 +620,6 @@ - - static - DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); --#define device_create_file_alarms(client) \ --device_create_file(&client->dev, &dev_attr_alarms); -- -- - - static ssize_t - show_pwm(struct device *dev, struct device_attribute *attr, -@@ -711,26 +707,19 @@ - return count; - } - --#define sysfs_pwm(offset) \ --static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ -- show_pwm, store_pwm, offset); \ --static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ -- show_pwmenable, store_pwmenable, offset); \ -- --sysfs_pwm(1); --sysfs_pwm(2); --sysfs_pwm(3); -- -- --#define device_create_file_pwm(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \ --} while (0) -- --#define device_create_file_pwmenable(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \ --} while (0) -+static struct sensor_device_attribute sda_pwm[] = { -+ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), -+ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), -+ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), -+}; -+static struct sensor_device_attribute sda_pwm_enable[] = { -+ SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, -+ show_pwmenable, store_pwmenable, 1), -+ SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, -+ show_pwmenable, store_pwmenable, 2), -+ SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, -+ show_pwmenable, store_pwmenable, 3), -+}; - - - static ssize_t -@@ -764,18 +753,14 @@ - return count; - } - --#define sysfs_pwm_mode(offset) \ --static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ -- show_pwm_mode, store_pwm_mode, offset); -- --sysfs_pwm_mode(1); --sysfs_pwm_mode(2); --sysfs_pwm_mode(3); -- --#define device_create_file_pwm_mode(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \ --} while (0) -+static struct sensor_device_attribute sda_pwm_mode[] = { -+ SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, -+ show_pwm_mode, store_pwm_mode, 1), -+ SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, -+ show_pwm_mode, store_pwm_mode, 2), -+ SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, -+ show_pwm_mode, store_pwm_mode, 3), -+}; - - - static ssize_t -@@ -788,12 +773,6 @@ - - static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); - --#define device_create_file_chassis(client) \ --do { \ --device_create_file(&client->dev, &dev_attr_chassis); \ --} while (0) -- -- - static ssize_t - show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) - { -@@ -824,13 +803,6 @@ - static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, - show_chassis_clear, store_chassis_clear); - --#define device_create_file_chassis_clear(client) \ --do { \ --device_create_file(&client->dev, &dev_attr_chassis_clear); \ --} while (0) -- -- -- - /* For Smart Fan I / Thermal Cruise */ - static ssize_t - show_thermal_cruise(struct device *dev, struct device_attribute *attr, -@@ -864,20 +836,14 @@ - return count; - } - --#define sysfs_thermal_cruise(offset) \ --static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ -- show_thermal_cruise, store_thermal_cruise, offset); -- --sysfs_thermal_cruise(1); --sysfs_thermal_cruise(2); --sysfs_thermal_cruise(3); -- --#define device_create_file_thermal_cruise(client, offset) \ --do { \ --device_create_file(&client->dev, \ --&sensor_dev_attr_thermal_cruise##offset.dev_attr); \ --} while (0) -- -+static struct sensor_device_attribute sda_thermal_cruise[] = { -+ SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, -+ show_thermal_cruise, store_thermal_cruise, 1), -+ SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, -+ show_thermal_cruise, store_thermal_cruise, 2), -+ SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, -+ show_thermal_cruise, store_thermal_cruise, 3), -+}; - - /* For Smart Fan I/Thermal Cruise and Smart Fan II */ - static ssize_t -@@ -916,19 +882,14 @@ - return count; - } - --#define sysfs_tolerance(offset) \ --static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ -- show_tolerance, store_tolerance, offset); -- --sysfs_tolerance(1); --sysfs_tolerance(2); --sysfs_tolerance(3); -- --#define device_create_file_tolerance(client, offset) \ --do { \ --device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \ --} while (0) -- -+static struct sensor_device_attribute sda_tolerance[] = { -+ SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO, -+ show_tolerance, store_tolerance, 1), -+ SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO, -+ show_tolerance, store_tolerance, 2), -+ SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO, -+ show_tolerance, store_tolerance, 3), -+}; - - /* For Smart Fan II */ - static ssize_t -@@ -964,28 +925,34 @@ - return count; - } - --#define sysfs_sf2_point(offset, index) \ --static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ -- show_sf2_point, store_sf2_point, offset, index); -- --sysfs_sf2_point(1, 1); /* Fan1 */ --sysfs_sf2_point(2, 1); /* Fan1 */ --sysfs_sf2_point(3, 1); /* Fan1 */ --sysfs_sf2_point(4, 1); /* Fan1 */ --sysfs_sf2_point(1, 2); /* Fan2 */ --sysfs_sf2_point(2, 2); /* Fan2 */ --sysfs_sf2_point(3, 2); /* Fan2 */ --sysfs_sf2_point(4, 2); /* Fan2 */ --sysfs_sf2_point(1, 3); /* Fan3 */ --sysfs_sf2_point(2, 3); /* Fan3 */ --sysfs_sf2_point(3, 3); /* Fan3 */ --sysfs_sf2_point(4, 3); /* Fan3 */ -- --#define device_create_file_sf2_point(client, offset, index) \ --do { \ --device_create_file(&client->dev, \ --&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ --} while (0) -+static struct sensor_device_attribute_2 sda_sf2_point[] = { -+ SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 1, 1), -+ SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 2, 1), -+ SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 3, 1), -+ SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 4, 1), -+ -+ SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 1, 2), -+ SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 2, 2), -+ SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 3, 2), -+ SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 4, 2), -+ -+ SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 1, 3), -+ SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 2, 3), -+ SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 3, 3), -+ SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_point, store_sf2_point, 4, 3), -+}; - - - static ssize_t -@@ -1026,39 +993,28 @@ - return count; - } - --#define sysfs_sf2_level(offset, index) \ --static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ -- show_sf2_level, store_sf2_level, offset, index); -- --sysfs_sf2_level(1, 1); /* Fan1 */ --sysfs_sf2_level(2, 1); /* Fan1 */ --sysfs_sf2_level(3, 1); /* Fan1 */ --sysfs_sf2_level(1, 2); /* Fan2 */ --sysfs_sf2_level(2, 2); /* Fan2 */ --sysfs_sf2_level(3, 2); /* Fan2 */ --sysfs_sf2_level(1, 3); /* Fan3 */ --sysfs_sf2_level(2, 3); /* Fan3 */ --sysfs_sf2_level(3, 3); /* Fan3 */ -- --#define device_create_file_sf2_level(client, offset, index) \ --do { \ --device_create_file(&client->dev, \ --&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \ --} while (0) -- -- --/* This function is called when: -- * w83792d_driver is inserted (when this module is loaded), for each -- available adapter -- * when a new adapter is inserted (and w83792d_driver is still present) */ --static int --w83792d_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, w83792d_detect); --} -- -+static struct sensor_device_attribute_2 sda_sf2_level[] = { -+ SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 1, 1), -+ SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 2, 1), -+ SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 3, 1), -+ -+ SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 1, 2), -+ SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 2, 2), -+ SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 3, 2), -+ -+ SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 1, 3), -+ SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 2, 3), -+ SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, -+ show_sf2_level, store_sf2_level, 3, 3), -+}; - - static int - w83792d_create_subclient(struct i2c_adapter *adapter, -@@ -1147,12 +1103,19 @@ - return err; - } - -+static void device_create_file_fan(struct device *dev, int i) -+{ -+ device_create_file(dev, &sda_fan_input[i].dev_attr); -+ device_create_file(dev, &sda_fan_div[i].dev_attr); -+ device_create_file(dev, &sda_fan_min[i].dev_attr); -+} - - static int - w83792d_detect(struct i2c_adapter *adapter, int address, int kind) - { - int i = 0, val1 = 0, val2; -- struct i2c_client *new_client; -+ struct i2c_client *client; -+ struct device *dev; - struct w83792d_data *data; - int err = 0; - const char *client_name = ""; -@@ -1170,12 +1133,13 @@ - goto ERROR0; - } - -- new_client = &data->client; -- i2c_set_clientdata(new_client, data); -- new_client->addr = address; -- new_client->adapter = adapter; -- new_client->driver = &w83792d_driver; -- new_client->flags = 0; -+ client = &data->client; -+ dev = &client->dev; -+ i2c_set_clientdata(client, data); -+ client->addr = address; -+ client->adapter = adapter; -+ client->driver = &w83792d_driver; -+ client->flags = 0; - - /* Now, we do the remaining detection. */ - -@@ -1184,50 +1148,49 @@ - force_*=... parameter, and the Winbond will be reset to the right - bank. */ - if (kind < 0) { -- if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) { -- dev_warn(&new_client->dev, "Detection failed at step " -- "3\n"); -+ if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { -+ dev_dbg(dev, "Detection failed at step 1\n"); - goto ERROR1; - } -- val1 = w83792d_read_value(new_client, W83792D_REG_BANK); -- val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); -+ val1 = w83792d_read_value(client, W83792D_REG_BANK); -+ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); - /* Check for Winbond ID if in bank 0 */ - if (!(val1 & 0x07)) { /* is Bank0 */ - if (((!(val1 & 0x80)) && (val2 != 0xa3)) || - ((val1 & 0x80) && (val2 != 0x5c))) { -+ dev_dbg(dev, "Detection failed at step 2\n"); - goto ERROR1; - } - } - /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR - should match */ -- if (w83792d_read_value(new_client, -+ if (w83792d_read_value(client, - W83792D_REG_I2C_ADDR) != address) { -- dev_warn(&new_client->dev, "Detection failed " -- "at step 5\n"); -+ dev_dbg(dev, "Detection failed at step 3\n"); - 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 */ -- w83792d_write_value(new_client, -+ w83792d_write_value(client, - W83792D_REG_BANK, -- (w83792d_read_value(new_client, -+ (w83792d_read_value(client, - W83792D_REG_BANK) & 0x78) | 0x80); - - /* Determine the chip type. */ - if (kind <= 0) { - /* get vendor ID */ -- val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); -+ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); - if (val2 != 0x5c) { /* the vendor is NOT Winbond */ - goto ERROR1; - } -- val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID); -+ val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); - if (val1 == 0x7a) { - kind = w83792d; - } else { - if (kind == 0) -- dev_warn(&new_client->dev, -+ dev_warn(dev, - "w83792d: Ignoring 'force' parameter for" - " unknown chip at adapter %d, address" - " 0x%02x\n", i2c_adapter_id(adapter), -@@ -1239,120 +1202,86 @@ - if (kind == w83792d) { - client_name = "w83792d"; - } else { -- dev_err(&new_client->dev, "w83792d: Internal error: unknown" -+ dev_err(dev, "w83792d: Internal error: unknown" - " kind (%d)?!?", kind); - goto ERROR1; - } - - /* Fill in the remaining client fields and put into the global list */ -- strlcpy(new_client->name, client_name, I2C_NAME_SIZE); -+ strlcpy(client->name, client_name, I2C_NAME_SIZE); - data->type = kind; - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ -- if ((err = i2c_attach_client(new_client))) -+ if ((err = i2c_attach_client(client))) - goto ERROR1; - - if ((err = w83792d_detect_subclients(adapter, address, -- kind, new_client))) -+ kind, client))) - goto ERROR2; - - /* Initialize the chip */ -- w83792d_init_client(new_client); -+ w83792d_init_client(client); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 7; i++) { -- data->fan_min[i] = w83792d_read_value(new_client, -+ data->fan_min[i] = w83792d_read_value(client, - W83792D_REG_FAN_MIN[i]); - } - - /* Register sysfs hooks */ -- data->class_dev = hwmon_device_register(&new_client->dev); -+ data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); - goto ERROR3; - } -- device_create_file_in(new_client, 0); -- 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); -- 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); -- device_create_file_fan(new_client, 3); -+ for (i = 0; i < 9; i++) { -+ device_create_file(dev, &sda_in_input[i].dev_attr); -+ device_create_file(dev, &sda_in_max[i].dev_attr); -+ device_create_file(dev, &sda_in_min[i].dev_attr); -+ } -+ for (i = 0; i < 3; i++) -+ device_create_file_fan(dev, i); - - /* Read GPIO enable register to check if pins for fan 4,5 are used as - GPIO */ -- val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); -+ val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); - if (!(val1 & 0x40)) -- device_create_file_fan(new_client, 4); -+ device_create_file_fan(dev, 3); - if (!(val1 & 0x20)) -- device_create_file_fan(new_client, 5); -+ device_create_file_fan(dev, 4); - -- val1 = w83792d_read_value(new_client, W83792D_REG_PIN); -+ val1 = w83792d_read_value(client, W83792D_REG_PIN); - if (val1 & 0x40) -- device_create_file_fan(new_client, 6); -+ device_create_file_fan(dev, 5); - if (val1 & 0x04) -- device_create_file_fan(new_client, 7); -+ device_create_file_fan(dev, 6); -+ -+ for (i = 0; i < 3; i++) { -+ device_create_file(dev, &sda_temp_input[i].dev_attr); -+ device_create_file(dev, &sda_temp_max[i].dev_attr); -+ device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); -+ device_create_file(dev, &sda_thermal_cruise[i].dev_attr); -+ device_create_file(dev, &sda_tolerance[i].dev_attr); -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { -+ device_create_file(dev, &sda_pwm[i].dev_attr); -+ device_create_file(dev, &sda_pwm_enable[i].dev_attr); -+ device_create_file(dev, &sda_pwm_mode[i].dev_attr); -+ } -+ -+ device_create_file(dev, &dev_attr_alarms); -+ device_create_file(dev, &dev_attr_chassis); -+ device_create_file(dev, &dev_attr_chassis_clear); -+ -+ for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) -+ device_create_file(dev, &sda_sf2_point[i].dev_attr); - -- device_create_file_temp1(new_client); /* Temp1 */ -- device_create_file_temp_add(new_client, 2); /* Temp2 */ -- device_create_file_temp_add(new_client, 3); /* Temp3 */ -- -- device_create_file_alarms(new_client); -- -- device_create_file_pwm(new_client, 1); -- device_create_file_pwm(new_client, 2); -- device_create_file_pwm(new_client, 3); -- -- device_create_file_pwmenable(new_client, 1); -- device_create_file_pwmenable(new_client, 2); -- device_create_file_pwmenable(new_client, 3); -- -- device_create_file_pwm_mode(new_client, 1); -- device_create_file_pwm_mode(new_client, 2); -- device_create_file_pwm_mode(new_client, 3); -- -- device_create_file_chassis(new_client); -- device_create_file_chassis_clear(new_client); -- -- device_create_file_thermal_cruise(new_client, 1); -- device_create_file_thermal_cruise(new_client, 2); -- device_create_file_thermal_cruise(new_client, 3); -- -- device_create_file_tolerance(new_client, 1); -- device_create_file_tolerance(new_client, 2); -- device_create_file_tolerance(new_client, 3); -- -- device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */ -- device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */ -- device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */ -- device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */ -- device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */ -- device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */ -- device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */ -- device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */ -- device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */ -- device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */ -- device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */ -- device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */ -- -- device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */ -- device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */ -- device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */ -- device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */ -- device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */ -- device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */ -- device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */ -- device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */ -- device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */ -+ for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++) -+ device_create_file(dev, &sda_sf2_level[i].dev_attr); - - return 0; - -@@ -1366,7 +1295,7 @@ - kfree(data->lm75[1]); - } - ERROR2: -- i2c_detach_client(new_client); -+ i2c_detach_client(client); - ERROR1: - kfree(data); - ERROR0: -@@ -1434,7 +1363,7 @@ - int i, j; - u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after - (jiffies - data->last_updated, (unsigned long) (HZ * 3)) -@@ -1545,7 +1474,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - #ifdef DEBUG - w83792d_print_debug(data, dev); ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd756-s4882.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-amd756-s4882.c 2006-03-22 17:06:15.000000000 +0100 -@@ -38,6 +38,7 @@ - #include <linux/slab.h> - #include <linux/init.h> - #include <linux/i2c.h> -+#include <linux/mutex.h> - - extern struct i2c_adapter amd756_smbus; - -@@ -45,7 +46,7 @@ - static struct i2c_algorithm *s4882_algo; - - /* Wrapper access functions for multiplexed SMBus */ --static struct semaphore amd756_lock; -+static DEFINE_MUTEX(amd756_lock); - - static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, -@@ -59,12 +60,12 @@ - || addr == 0x18) - return -1; - -- down(&amd756_lock); -+ mutex_lock(&amd756_lock); - - error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - -- up(&amd756_lock); -+ mutex_unlock(&amd756_lock); - - return error; - } -@@ -87,7 +88,7 @@ - if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) - return -1; - -- down(&amd756_lock); -+ mutex_lock(&amd756_lock); - - if (last_channels != channels) { - union i2c_smbus_data mplxdata; -@@ -105,7 +106,7 @@ - command, size, data); - - UNLOCK: -- up(&amd756_lock); -+ mutex_unlock(&amd756_lock); - return error; - } - -@@ -166,8 +167,6 @@ - } - - printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); -- init_MUTEX(&amd756_lock); -- - /* Define the 5 virtual adapters and algorithms structures */ - if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), - GFP_KERNEL))) { ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-isa.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-isa.c 2006-03-22 17:06:15.000000000 +0100 -@@ -125,7 +125,7 @@ - - static int __init i2c_isa_init(void) - { -- init_MUTEX(&isa_adapter.clist_lock); -+ mutex_init(&isa_adapter.clist_lock); - INIT_LIST_HEAD(&isa_adapter.clients); - - isa_adapter.nr = ANY_I2C_ISA_BUS; ---- linux-2.6.16.orig/drivers/i2c/chips/eeprom.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/eeprom.c 2006-03-22 17:06:16.000000000 +0100 -@@ -33,6 +33,7 @@ - #include <linux/sched.h> - #include <linux/jiffies.h> - #include <linux/i2c.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, -@@ -54,7 +55,7 @@ - /* Each client has this additional data */ - struct eeprom_data { - struct i2c_client client; -- struct semaphore update_lock; -+ struct mutex update_lock; - u8 valid; /* bitfield, bit!=0 if slice is valid */ - unsigned long last_updated[8]; /* In jiffies, 8 slices */ - u8 data[EEPROM_SIZE]; /* Register values */ -@@ -62,7 +63,6 @@ - }; - - --static int eeprom_attach_adapter(struct i2c_adapter *adapter); - static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); - static int eeprom_detach_client(struct i2c_client *client); - -@@ -72,7 +72,9 @@ - .name = "eeprom", - }, - .id = I2C_DRIVERID_EEPROM, -- .attach_adapter = eeprom_attach_adapter, -+ .class = I2C_CLASS_DATA, -+ .address_data = &addr_data, -+ .detect_client = eeprom_detect, - .detach_client = eeprom_detach_client, - }; - -@@ -81,7 +83,7 @@ - struct eeprom_data *data = i2c_get_clientdata(client); - int i, j; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (!(data->valid & (1 << slice)) || - time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { -@@ -107,7 +109,7 @@ - data->valid |= (1 << slice); - } - exit: -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) -@@ -149,11 +151,6 @@ - .read = eeprom_read, - }; - --static int eeprom_attach_adapter(struct i2c_adapter *adapter) --{ -- return i2c_probe(adapter, &addr_data, eeprom_detect); --} -- - /* This function is called by i2c_probe */ - static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) - { -@@ -187,7 +184,7 @@ - /* Fill in the remaining client fields */ - strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - data->nature = UNKNOWN; - - /* Tell the I2C layer a new client has arrived */ ---- linux-2.6.16.orig/drivers/i2c/chips/max6875.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/max6875.c 2006-03-22 17:06:15.000000000 +0100 -@@ -31,7 +31,7 @@ - #include <linux/module.h> - #include <linux/slab.h> - #include <linux/i2c.h> --#include <asm/semaphore.h> -+#include <linux/mutex.h> - - /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ - static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -@@ -54,7 +54,7 @@ - /* Each client has this additional data */ - struct max6875_data { - struct i2c_client client; -- struct semaphore update_lock; -+ struct mutex update_lock; - - u32 valid; - u8 data[USER_EEPROM_SIZE]; -@@ -83,7 +83,7 @@ - if (slice >= USER_EEPROM_SLICES) - return; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - buf = &data->data[slice << SLICE_BITS]; - -@@ -122,7 +122,7 @@ - data->valid |= (1 << slice); - } - exit_up: -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, -@@ -196,7 +196,7 @@ - real_client->driver = &max6875_driver; - real_client->flags = 0; - strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Init fake client data */ - /* set the client data to the i2c_client so that it will get freed */ ---- linux-2.6.16.orig/drivers/i2c/chips/pcf8591.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/pcf8591.c 2006-03-22 17:06:15.000000000 +0100 -@@ -24,6 +24,7 @@ - #include <linux/init.h> - #include <linux/slab.h> - #include <linux/i2c.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, -@@ -74,7 +75,7 @@ - - struct pcf8591_data { - struct i2c_client client; -- struct semaphore update_lock; -+ struct mutex update_lock; - - u8 control; - u8 aout; -@@ -144,13 +145,13 @@ - struct pcf8591_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (val) - data->control |= PCF8591_CONTROL_AOEF; - else - data->control &= ~PCF8591_CONTROL_AOEF; - i2c_smbus_write_byte(client, data->control); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -200,7 +201,7 @@ - /* Fill in the remaining client fields and put it into the global - list */ - strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -265,7 +266,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { - data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) -@@ -278,7 +279,7 @@ - } - value = i2c_smbus_read_byte(client); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - if ((channel == 2 && input_mode == 2) || - (channel != 3 && (input_mode == 1 || input_mode == 3))) ---- linux-2.6.16.orig/drivers/i2c/chips/tps65010.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/tps65010.c 2006-03-22 17:06:15.000000000 +0100 -@@ -32,6 +32,7 @@ - #include <linux/suspend.h> - #include <linux/debugfs.h> - #include <linux/seq_file.h> -+#include <linux/mutex.h> - - #include <asm/irq.h> - #include <asm/mach-types.h> -@@ -81,7 +82,7 @@ - - struct tps65010 { - struct i2c_client client; -- struct semaphore lock; -+ struct mutex lock; - int irq; - struct work_struct work; - struct dentry *file; -@@ -218,7 +219,7 @@ - seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", - DRIVER_NAME, DRIVER_VERSION, chip); - -- down(&tps->lock); -+ mutex_lock(&tps->lock); - - /* FIXME how can we tell whether a battery is present? - * likely involves a charge gauging chip (like BQ26501). -@@ -300,7 +301,7 @@ - (v2 & (1 << (4 + i))) ? "rising" : "falling"); - } - -- up(&tps->lock); -+ mutex_unlock(&tps->lock); - return 0; - } - -@@ -416,7 +417,7 @@ - { - struct tps65010 *tps = _tps; - -- down(&tps->lock); -+ mutex_lock(&tps->lock); - - tps65010_interrupt(tps); - -@@ -444,7 +445,7 @@ - if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) - enable_irq(tps->irq); - -- up(&tps->lock); -+ mutex_unlock(&tps->lock); - } - - static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) -@@ -505,7 +506,7 @@ - if (!tps) - return 0; - -- init_MUTEX(&tps->lock); -+ mutex_init(&tps->lock); - INIT_WORK(&tps->work, tps65010_work, tps); - tps->irq = -1; - tps->client.addr = address; -@@ -695,7 +696,7 @@ - if ((gpio < GPIO1) || (gpio > GPIO4)) - return -EINVAL; - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); - -@@ -720,7 +721,7 @@ - gpio, value ? "high" : "low", - i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return status; - } - EXPORT_SYMBOL(tps65010_set_gpio_out_value); -@@ -745,7 +746,7 @@ - led = LED2; - } - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, - i2c_smbus_read_byte_data(&the_tps->client, -@@ -771,7 +772,7 @@ - default: - printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", - DRIVER_NAME); -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return -EINVAL; - } - -@@ -781,7 +782,7 @@ - if (status != 0) { - printk(KERN_ERR "%s: Failed to write led%i_on register\n", - DRIVER_NAME, led); -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return status; - } - -@@ -794,7 +795,7 @@ - if (status != 0) { - printk(KERN_ERR "%s: Failed to write led%i_per register\n", - DRIVER_NAME, led); -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return status; - } - -@@ -802,7 +803,7 @@ - i2c_smbus_read_byte_data(&the_tps->client, - TPS_LED1_PER + offs)); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - - return status; - } -@@ -820,7 +821,7 @@ - if (!the_tps) - return -ENODEV; - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); - vdcdc2 &= ~(1 << 1); -@@ -831,7 +832,7 @@ - - pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return status; - } - EXPORT_SYMBOL(tps65010_set_vib); -@@ -848,7 +849,7 @@ - if (!the_tps) - return -ENODEV; - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, - mode ? "enable" : "disable", -@@ -876,7 +877,7 @@ - pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - - return status; - } -@@ -894,7 +895,7 @@ - if (!the_tps) - return -ENODEV; - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); -@@ -909,7 +910,7 @@ - pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - - return status; - } -@@ -931,7 +932,7 @@ - if (!the_tps || the_tps->por) - return -ENODEV; - -- down(&the_tps->lock); -+ mutex_lock(&the_tps->lock); - - pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", - DRIVER_NAME, -@@ -959,7 +960,7 @@ - if (status != 0) { - printk(KERN_ERR "%s: Failed to write chconfig register\n", - DRIVER_NAME); -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - return status; - } - -@@ -977,7 +978,7 @@ - pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); - -- up(&the_tps->lock); -+ mutex_unlock(&the_tps->lock); - - return status; - } ---- linux-2.6.16.orig/include/linux/i2c.h 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/include/linux/i2c.h 2006-03-22 17:06:21.000000000 +0100 -@@ -32,7 +32,7 @@ - #include <linux/mod_devicetable.h> - #include <linux/device.h> /* for struct device */ - #include <linux/sched.h> /* for completion */ --#include <asm/semaphore.h> -+#include <linux/mutex.h> - - /* --- For i2c-isa ---------------------------------------------------- */ - -@@ -48,6 +48,7 @@ - struct i2c_adapter; - struct i2c_client; - struct i2c_driver; -+struct i2c_client_address_data; - union i2c_smbus_data; - - /* -@@ -116,6 +117,7 @@ - struct i2c_driver { - int id; - unsigned int class; -+ struct i2c_client_address_data *address_data; - - /* Notifies the driver that a new bus has appeared. This routine - * can be used by the driver to test if the bus meets its conditions -@@ -133,6 +135,15 @@ - */ - int (*detach_client)(struct i2c_client *); - -+ /* Requests that the driver validate an address on a bus and attach a -+ * new client. If this routine is supplied, it will be called for -+ * each device on new buses that appear, provided the bus class -+ * matches the class field and devices exist at the addresses listed -+ * in the address_data field. For most drivers, this mechanism can -+ * be used instead of an attach_adapter routine. -+ */ -+ int (*detect_client)(struct i2c_adapter *, int addr, int kind); -+ - /* a ioctl like command that can be used to perform specific functions - * with the device. - */ -@@ -225,8 +236,8 @@ - int (*client_unregister)(struct i2c_client *); - - /* data fields that are valid for all devices */ -- struct semaphore bus_lock; -- struct semaphore clist_lock; -+ struct mutex bus_lock; -+ struct mutex clist_lock; - - int timeout; - int retries; -@@ -262,7 +273,7 @@ - #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ - #define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */ - #define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */ --#define I2C_CLASS_DDC (1<<3) /* i2c-matroxfb ? */ -+#define I2C_CLASS_DATA (1<<3) /* data storage */ - #define I2C_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */ - #define I2C_CLASS_CAM_DIGITAL (1<<5) /* most webcams */ - #define I2C_CLASS_SOUND (1<<6) /* sound devices */ -@@ -329,6 +340,10 @@ - struct i2c_client_address_data *address_data, - int (*found_proc) (struct i2c_adapter *, int, int)); - -+/* Direct chip probing function to create clients by address */ -+extern int i2c_probe_device(struct i2c_adapter *adapter, int driver_id, -+ int addr, int kind); -+ - /* An ioctl like call to set div. parameters of the adapter. - */ - extern int i2c_control(struct i2c_client *,unsigned int, unsigned long); ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-pxa.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-pxa.c 2006-03-22 17:06:15.000000000 +0100 -@@ -647,7 +647,7 @@ - } - - /* -- * We are protected by the adapter bus semaphore. -+ * We are protected by the adapter bus mutex. - */ - static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) - { ---- linux-2.6.16.orig/drivers/hwmon/adm1021.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/adm1021.c 2006-03-22 17:06:16.000000000 +0100 -@@ -26,6 +26,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - - /* Addresses to scan */ -@@ -92,7 +93,7 @@ - struct class_device *class_dev; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -111,7 +112,6 @@ - u8 remote_temp_offset_prec; - }; - --static int adm1021_attach_adapter(struct i2c_adapter *adapter); - 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); -@@ -130,7 +130,9 @@ - .name = "adm1021", - }, - .id = I2C_DRIVERID_ADM1021, -- .attach_adapter = adm1021_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = adm1021_detect, - .detach_client = adm1021_detach_client, - }; - -@@ -162,10 +164,10 @@ - struct adm1021_data *data = i2c_get_clientdata(client); \ - int temp = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(temp); \ - adm1021_write_value(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - set(temp_max, ADM1021_REG_TOS_W); -@@ -182,13 +184,6 @@ - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - - --static int adm1021_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, adm1021_detect); --} -- - static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) - { - int i; -@@ -275,7 +270,7 @@ - strlcpy(new_client->name, type_name, I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -351,7 +346,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -375,7 +370,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/adm1025.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/adm1025.c 2006-03-22 17:06:16.000000000 +0100 -@@ -53,6 +53,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -107,7 +108,6 @@ - * Functions declaration - */ - --static int adm1025_attach_adapter(struct i2c_adapter *adapter); - static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); - static void adm1025_init_client(struct i2c_client *client); - static int adm1025_detach_client(struct i2c_client *client); -@@ -122,7 +122,9 @@ - .name = "adm1025", - }, - .id = I2C_DRIVERID_ADM1025, -- .attach_adapter = adm1025_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = adm1025_detect, - .detach_client = adm1025_detach_client, - }; - -@@ -133,7 +135,7 @@ - struct adm1025_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -207,11 +209,11 @@ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ - data->in_min[offset]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } \ - static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ -@@ -221,11 +223,11 @@ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ - data->in_max[offset]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } \ - static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ -@@ -247,11 +249,11 @@ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->temp_min[offset-1] = TEMP_TO_REG(val); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ - data->temp_min[offset-1]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } \ - static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ -@@ -261,11 +263,11 @@ - struct adm1025_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->temp_max[offset-1] = TEMP_TO_REG(val); \ - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ - data->temp_max[offset-1]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } \ - static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ -@@ -307,13 +309,6 @@ - * Real code - */ - --static int adm1025_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, adm1025_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -404,7 +399,7 @@ - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -523,7 +518,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - int i; -@@ -558,7 +553,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/adm1026.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/adm1026.c 2006-03-22 17:06:21.000000000 +0100 -@@ -32,6 +32,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; -@@ -260,10 +261,10 @@ - struct adm1026_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_reading; /* In jiffies */ - unsigned long last_config; /* In jiffies */ -@@ -294,13 +295,11 @@ - u8 config3; /* Register value */ - }; - --static int adm1026_attach_adapter(struct i2c_adapter *adapter); - static int adm1026_detect(struct i2c_adapter *adapter, int address, - int kind); - static int adm1026_detach_client(struct i2c_client *client); --static int adm1026_read_value(struct i2c_client *client, u8 register); --static int adm1026_write_value(struct i2c_client *client, u8 register, -- int value); -+static int adm1026_read_value(struct i2c_client *client, u8 reg); -+static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); - static void adm1026_print_gpio(struct i2c_client *client); - static void adm1026_fixup_gpio(struct i2c_client *client); - static struct adm1026_data *adm1026_update_device(struct device *dev); -@@ -311,18 +310,12 @@ - .driver = { - .name = "adm1026", - }, -- .attach_adapter = adm1026_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = adm1026_detect, - .detach_client = adm1026_detach_client, - }; - --static int adm1026_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) { -- return 0; -- } -- return i2c_probe(adapter, &addr_data, adm1026_detect); --} -- - static int adm1026_detach_client(struct i2c_client *client) - { - struct adm1026_data *data = i2c_get_clientdata(client); -@@ -575,7 +568,7 @@ - int i; - long value, alarms, gpio; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (!data->valid - || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { - /* Things that change quickly */ -@@ -710,7 +703,7 @@ - dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); - data->vid = (data->gpio >> 11) & 0x1f; - data->valid = 1; -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return data; - } - -@@ -739,10 +732,10 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = INS_TO_REG(nr, val); - adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, -@@ -762,10 +755,10 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = INS_TO_REG(nr, val); - adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -813,10 +806,10 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); - adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) -@@ -831,10 +824,10 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); - adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -874,11 +867,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); - adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), - data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -939,7 +932,7 @@ - if (new_div == 0) { - return -EINVAL; - } -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - orig_div = data->fan_div[nr]; - data->fan_div[nr] = DIV_FROM_REG(new_div); - -@@ -958,7 +951,7 @@ - if (data->fan_div[nr] != orig_div) { - fixup_fan_min(dev,nr,orig_div); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1001,11 +994,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], - data->temp_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, -@@ -1025,11 +1018,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], - data->temp_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1064,11 +1057,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_offset[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], - data->temp_offset[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1115,11 +1108,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_tmin[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], - data->temp_tmin[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1150,11 +1143,11 @@ - int val = simple_strtol(buf, NULL, 10); - - if ((val == 1) || (val==0)) { -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); - adm1026_write_value(client, ADM1026_REG_CONFIG1, - data->config1); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - return count; - } -@@ -1184,11 +1177,11 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_crit[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], - data->temp_crit[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1212,10 +1205,10 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->analog_out = DAC_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1267,7 +1260,7 @@ - int val = simple_strtol(buf, NULL, 10); - unsigned long mask; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->alarm_mask = val & 0x7fffffff; - mask = data->alarm_mask - | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); -@@ -1282,7 +1275,7 @@ - mask >>= 8; - adm1026_write_value(client, ADM1026_REG_MASK4, - mask & 0xff); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1303,7 +1296,7 @@ - int val = simple_strtol(buf, NULL, 10); - long gpio; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->gpio = val & 0x1ffff; - gpio = data->gpio; - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); -@@ -1311,7 +1304,7 @@ - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); - gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1331,7 +1324,7 @@ - int val = simple_strtol(buf, NULL, 10); - long mask; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->gpio_mask = val & 0x1ffff; - mask = data->gpio_mask; - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); -@@ -1339,7 +1332,7 @@ - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); - mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -1359,10 +1352,10 @@ - if (data->pwm1.enable == 1) { - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm1.pwm = PWM_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - return count; - } -@@ -1378,14 +1371,14 @@ - struct adm1026_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); - if (data->pwm1.enable == 2) { /* apply immediately */ - data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | - PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) -@@ -1406,7 +1399,7 @@ - int old_enable; - - if ((val >= 0) && (val < 3)) { -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - old_enable = data->pwm1.enable; - data->pwm1.enable = val; - data->config1 = (data->config1 & ~CFG1_PWM_AFC) -@@ -1424,7 +1417,7 @@ - adm1026_write_value(client, ADM1026_REG_PWM, - data->pwm1.pwm); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - return count; - } -@@ -1541,7 +1534,7 @@ - /* Fill in the remaining client fields */ - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) ---- linux-2.6.16.orig/drivers/hwmon/adm1031.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/adm1031.c 2006-03-22 17:06:16.000000000 +0100 -@@ -28,6 +28,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Following macros takes channel parameter starting from 0 to 2 */ - #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) -@@ -70,7 +71,7 @@ - struct adm1031_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - int chip_type; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ -@@ -97,7 +98,6 @@ - s8 temp_crit[3]; - }; - --static int adm1031_attach_adapter(struct i2c_adapter *adapter); - static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); - static void adm1031_init_client(struct i2c_client *client); - static int adm1031_detach_client(struct i2c_client *client); -@@ -108,7 +108,9 @@ - .driver = { - .name = "adm1031", - }, -- .attach_adapter = adm1031_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = adm1031_detect, - .detach_client = adm1031_detach_client, - }; - -@@ -262,10 +264,10 @@ - - old_fan_mode = data->conf1; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return ret; - } - if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ -@@ -288,7 +290,7 @@ - } - data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); - adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -329,11 +331,11 @@ - struct adm1031_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); - adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), - data->auto_temp[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) -@@ -349,11 +351,11 @@ - struct adm1031_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); - adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), - data->temp_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -405,11 +407,11 @@ - int val = simple_strtol(buf, NULL, 10); - int reg; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && - (((val>>4) & 0xf) != 5)) { - /* In automatic mode, the only PWM accepted is 33% */ -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - data->pwm[nr] = PWM_TO_REG(val); -@@ -417,7 +419,7 @@ - adm1031_write_value(client, ADM1031_REG_PWM, - nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) - : (data->pwm[nr] & 0xf) | (reg & 0xf0)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -511,7 +513,7 @@ - struct adm1031_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (val) { - data->fan_min[nr] = - FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); -@@ -519,7 +521,7 @@ - data->fan_min[nr] = 0xff; - } - adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t -@@ -540,7 +542,7 @@ - if (tmp == 0xff) - return -EINVAL; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); - data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); - new_min = data->fan_min[nr] * old_div / -@@ -553,7 +555,7 @@ - data->fan_div[nr]); - adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), - data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -627,11 +629,11 @@ - - val = simple_strtol(buf, NULL, 10); - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), - data->temp_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t -@@ -643,11 +645,11 @@ - - val = simple_strtol(buf, NULL, 10); - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), - data->temp_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t -@@ -659,11 +661,11 @@ - - val = simple_strtol(buf, NULL, 10); - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_crit[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), - data->temp_crit[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -722,13 +724,6 @@ - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - - --static int adm1031_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, adm1031_detect); --} -- - /* This function is called by i2c_probe */ - static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) - { -@@ -778,7 +773,7 @@ - - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -891,7 +886,7 @@ - struct adm1031_data *data = i2c_get_clientdata(client); - int chan; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -965,7 +960,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/adm9240.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/adm9240.c 2006-03-22 17:06:16.000000000 +0100 -@@ -49,6 +49,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, -@@ -129,7 +130,6 @@ - return SCALE(reg, 1250, 255); - } - --static int adm9240_attach_adapter(struct i2c_adapter *adapter); - static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind); - static void adm9240_init_client(struct i2c_client *client); - static int adm9240_detach_client(struct i2c_client *client); -@@ -141,7 +141,9 @@ - .name = "adm9240", - }, - .id = I2C_DRIVERID_ADM9240, -- .attach_adapter = adm9240_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = adm9240_detect, - .detach_client = adm9240_detach_client, - }; - -@@ -150,7 +152,7 @@ - enum chips type; - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; - unsigned long last_updated_measure; - unsigned long last_updated_config; -@@ -195,11 +197,11 @@ - struct adm9240_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[attr->index] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), - data->temp_max[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -246,11 +248,11 @@ - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, attr->index); - i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), - data->in_min[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -263,11 +265,11 @@ - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, attr->index); - i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), - data->in_max[attr->index]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -350,7 +352,7 @@ - int nr = attr->index; - u8 new_div; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (!val) { - data->fan_min[nr] = 255; -@@ -390,7 +392,7 @@ - i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), - data->fan_min[nr]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -439,10 +441,10 @@ - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->aout = AOUT_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); -@@ -539,7 +541,7 @@ - /* fill in the remaining client fields and attach */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->type = kind; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - if ((err = i2c_attach_client(new_client))) - goto exit_free; -@@ -621,13 +623,6 @@ - return err; - } - --static int adm9240_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, adm9240_detect); --} -- - static int adm9240_detach_client(struct i2c_client *client) - { - struct adm9240_data *data = i2c_get_clientdata(client); -@@ -691,7 +686,7 @@ - struct adm9240_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - /* minimum measurement cycle: 1.75 seconds */ - if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) -@@ -771,7 +766,7 @@ - data->last_updated_config = jiffies; - data->valid = 1; - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return data; - } - ---- linux-2.6.16.orig/drivers/hwmon/asb100.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/asb100.c 2006-03-22 17:06:16.000000000 +0100 -@@ -44,6 +44,7 @@ - #include <linux/err.h> - #include <linux/init.h> - #include <linux/jiffies.h> -+#include <linux/mutex.h> - #include "lm75.h" - - /* -@@ -182,10 +183,10 @@ - struct asb100_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - - /* array of 2 pointers to subclients */ -@@ -210,7 +211,6 @@ - static int asb100_read_value(struct i2c_client *client, u16 reg); - static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); - --static int asb100_attach_adapter(struct i2c_adapter *adapter); - static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); - static int asb100_detach_client(struct i2c_client *client); - static struct asb100_data *asb100_update_device(struct device *dev); -@@ -221,7 +221,9 @@ - .name = "asb100", - }, - .id = I2C_DRIVERID_ASB100, -- .attach_adapter = asb100_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = asb100_detect, - .detach_client = asb100_detach_client, - }; - -@@ -245,11 +247,11 @@ - struct asb100_data *data = i2c_get_clientdata(client); \ - unsigned long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -331,10 +333,10 @@ - struct asb100_data *data = i2c_get_clientdata(client); - u32 val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -351,7 +353,7 @@ - unsigned long val = simple_strtoul(buf, NULL, 10); - int reg; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); -@@ -381,7 +383,7 @@ - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -461,7 +463,7 @@ - struct asb100_data *data = i2c_get_clientdata(client); \ - unsigned long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - switch (nr) { \ - case 1: case 2: \ - data->reg[nr] = LM75_TEMP_TO_REG(val); \ -@@ -472,7 +474,7 @@ - } \ - asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ - data->reg[nr]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -574,11 +576,11 @@ - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm &= 0x80; /* keep the enable bit */ - data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); - asb100_write_value(client, ASB100_REG_PWM1, data->pwm); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -595,11 +597,11 @@ - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm &= 0x0f; /* keep the duty cycle bits */ - data->pwm |= (val ? 0x80 : 0x00); - asb100_write_value(client, ASB100_REG_PWM1, data->pwm); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -611,18 +613,6 @@ - device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \ - } while (0) - --/* This function is called when: -- asb100_driver is inserted (when this module is loaded), for each -- available adapter -- when a new adapter is inserted (and asb100_driver is still present) -- */ --static int asb100_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, asb100_detect); --} -- - static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, - int kind, struct i2c_client *new_client) - { -@@ -729,7 +719,7 @@ - } - - new_client = &data->client; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; -@@ -789,7 +779,7 @@ - data->type = kind; - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -885,7 +875,7 @@ - struct i2c_client *cl; - int res, bank; - -- down(&data->lock); -+ mutex_lock(&data->lock); - - bank = (reg >> 8) & 0x0f; - if (bank > 2) -@@ -919,7 +909,7 @@ - if (bank > 2) - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - -- up(&data->lock); -+ mutex_unlock(&data->lock); - - return res; - } -@@ -930,7 +920,7 @@ - struct i2c_client *cl; - int bank; - -- down(&data->lock); -+ mutex_lock(&data->lock); - - bank = (reg >> 8) & 0x0f; - if (bank > 2) -@@ -960,7 +950,7 @@ - if (bank > 2) - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - -- up(&data->lock); -+ mutex_unlock(&data->lock); - } - - static void asb100_init_client(struct i2c_client *client) -@@ -984,7 +974,7 @@ - struct asb100_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -1042,7 +1032,7 @@ - dev_dbg(&client->dev, "... device update complete\n"); - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/atxp1.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/atxp1.c 2006-03-22 17:06:16.000000000 +0100 -@@ -26,6 +26,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); -@@ -44,7 +45,6 @@ - - I2C_CLIENT_INSMOD_1(atxp1); - --static int atxp1_attach_adapter(struct i2c_adapter * adapter); - static int atxp1_detach_client(struct i2c_client * client); - static struct atxp1_data * atxp1_update_device(struct device *dev); - static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); -@@ -53,14 +53,16 @@ - .driver = { - .name = "atxp1", - }, -- .attach_adapter = atxp1_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = atxp1_detect, - .detach_client = atxp1_detach_client, - }; - - struct atxp1_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - unsigned long last_updated; - u8 valid; - struct { -@@ -80,7 +82,7 @@ - client = to_i2c_client(dev); - data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - -@@ -93,7 +95,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return(data); - } -@@ -251,13 +253,6 @@ - static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); - - --static int atxp1_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, &atxp1_detect); --}; -- - static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) - { - struct i2c_client * new_client; -@@ -309,7 +304,7 @@ - - data->valid = 0; - -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - err = i2c_attach_client(new_client); - ---- linux-2.6.16.orig/drivers/hwmon/ds1621.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/ds1621.c 2006-03-22 17:06:16.000000000 +0100 -@@ -28,6 +28,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include "lm75.h" - - /* Addresses to scan */ -@@ -72,7 +73,7 @@ - struct ds1621_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -80,7 +81,6 @@ - u8 conf; /* Register encoding, combined */ - }; - --static int ds1621_attach_adapter(struct i2c_adapter *adapter); - static int ds1621_detect(struct i2c_adapter *adapter, int address, - int kind); - static void ds1621_init_client(struct i2c_client *client); -@@ -93,7 +93,9 @@ - .name = "ds1621", - }, - .id = I2C_DRIVERID_DS1621, -- .attach_adapter = ds1621_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = ds1621_detect, - .detach_client = ds1621_detach_client, - }; - -@@ -156,10 +158,10 @@ - struct ds1621_data *data = ds1621_update_client(dev); \ - u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = val; \ - ds1621_write_value(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -178,13 +180,6 @@ - static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); - - --static int ds1621_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, ds1621_detect); --} -- - /* This function is called by i2c_probe */ - static int ds1621_detect(struct i2c_adapter *adapter, int address, - int kind) -@@ -242,7 +237,7 @@ - /* Fill in remaining client fields and put it into the global list */ - strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -297,7 +292,7 @@ - struct ds1621_data *data = i2c_get_clientdata(client); - u8 new_conf; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -327,7 +322,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/fscher.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/fscher.c 2006-03-22 17:06:16.000000000 +0100 -@@ -33,6 +33,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -104,7 +105,6 @@ - * Functions declaration - */ - --static int fscher_attach_adapter(struct i2c_adapter *adapter); - static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); - static int fscher_detach_client(struct i2c_client *client); - static struct fscher_data *fscher_update_device(struct device *dev); -@@ -122,7 +122,9 @@ - .name = "fscher", - }, - .id = I2C_DRIVERID_FSCHER, -- .attach_adapter = fscher_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = fscher_detect, - .detach_client = fscher_detach_client, - }; - -@@ -133,7 +135,7 @@ - struct fscher_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -284,13 +286,6 @@ - * Real code - */ - --static int fscher_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, fscher_detect); --} -- - static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) - { - struct i2c_client *new_client; -@@ -332,7 +327,7 @@ - * global list */ - strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -417,7 +412,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct fscher_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - -@@ -457,7 +452,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } -@@ -472,10 +467,10 @@ - /* bits 0..1, 3..7 reserved => mask with 0x04 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; - fscher_write_value(client, reg, v); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -490,10 +485,10 @@ - { - unsigned long v = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; - fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -518,14 +513,14 @@ - return -EINVAL; - } - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - /* bits 2..7 reserved => mask with 0x03 */ - data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; - data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; - - fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -552,10 +547,10 @@ - /* bits 2..7 reserved, 0 read only => mask with 0x02 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; - fscher_write_value(client, reg, v); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -609,10 +604,10 @@ - /* bits 1..7 reserved => mask with 0x01 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->global_control &= ~v; - fscher_write_value(client, reg, v); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -631,11 +626,11 @@ - /* bits 0..3 reserved => mask with 0xf0 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->watchdog[2] &= ~0xf0; - data->watchdog[2] |= v; - fscher_write_value(client, reg, data->watchdog[2]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -651,10 +646,10 @@ - /* bits 0, 2..7 reserved => mask with 0x02 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->watchdog[1] &= ~v; - fscher_write_value(client, reg, v); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -669,10 +664,10 @@ - { - unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->watchdog[0] = v; - fscher_write_value(client, reg, data->watchdog[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - ---- linux-2.6.16.orig/drivers/hwmon/fscpos.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/fscpos.c 2006-03-22 17:06:16.000000000 +0100 -@@ -37,6 +37,7 @@ - #include <linux/init.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -85,12 +86,11 @@ - /* - * Functions declaration - */ --static int fscpos_attach_adapter(struct i2c_adapter *adapter); - static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); - static int fscpos_detach_client(struct i2c_client *client); - --static int fscpos_read_value(struct i2c_client *client, u8 register); --static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value); -+static int fscpos_read_value(struct i2c_client *client, u8 reg); -+static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); - static struct fscpos_data *fscpos_update_device(struct device *dev); - static void fscpos_init_client(struct i2c_client *client); - -@@ -104,7 +104,9 @@ - .name = "fscpos", - }, - .id = I2C_DRIVERID_FSCPOS, -- .attach_adapter = fscpos_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = fscpos_detect, - .detach_client = fscpos_detach_client, - }; - -@@ -114,7 +116,7 @@ - struct fscpos_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* 0 until following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -208,13 +210,13 @@ - return -EINVAL; - } - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - /* bits 2..7 reserved => mask with 0x03 */ - data->fan_ripple[nr - 1] &= ~0x03; - data->fan_ripple[nr - 1] |= v; - - fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -232,10 +234,10 @@ - if (v < 0) v = 0; - if (v > 255) v = 255; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[nr - 1] = v; - fscpos_write_value(client, reg, data->pwm[nr - 1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -278,11 +280,11 @@ - /* bits 0..3 reserved => mask with 0xf0 */ - unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->wdog_control &= ~0xf0; - data->wdog_control |= v; - fscpos_write_value(client, reg, data->wdog_control); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -304,10 +306,10 @@ - return -EINVAL; - } - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->wdog_state &= ~v; - fscpos_write_value(client, reg, v); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -321,10 +323,10 @@ - { - unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->wdog_preset = v; - fscpos_write_value(client, reg, data->wdog_preset); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -431,13 +433,6 @@ - static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); - static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); - --static int fscpos_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, fscpos_detect); --} -- - static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) - { - struct i2c_client *new_client; -@@ -483,7 +478,7 @@ - strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -579,7 +574,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct fscpos_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - int i; -@@ -625,7 +620,7 @@ - data->last_updated = jiffies; - data->valid = 1; - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return data; - } - ---- linux-2.6.16.orig/drivers/hwmon/gl518sm.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/gl518sm.c 2006-03-22 17:06:16.000000000 +0100 -@@ -43,6 +43,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; -@@ -120,7 +121,7 @@ - struct class_device *class_dev; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -141,7 +142,6 @@ - u8 beep_enable; /* Boolean */ - }; - --static int gl518_attach_adapter(struct i2c_adapter *adapter); - static int gl518_detect(struct i2c_adapter *adapter, int address, int kind); - static void gl518_init_client(struct i2c_client *client); - static int gl518_detach_client(struct i2c_client *client); -@@ -155,7 +155,9 @@ - .name = "gl518sm", - }, - .id = I2C_DRIVERID_GL518, -- .attach_adapter = gl518_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = gl518_detect, - .detach_client = gl518_detach_client, - }; - -@@ -212,10 +214,10 @@ - struct gl518_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = type##_TO_REG(val); \ - gl518_write_value(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -228,12 +230,12 @@ - int regvalue; \ - unsigned long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - regvalue = gl518_read_value(client, reg); \ - data->value = type##_TO_REG(val); \ - regvalue = (regvalue & ~mask) | (data->value << shift); \ - gl518_write_value(client, reg, regvalue); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -265,7 +267,7 @@ - int regvalue; - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[0] = FAN_TO_REG(val, - DIV_FROM_REG(data->fan_div[0])); -@@ -280,7 +282,7 @@ - data->beep_mask &= data->alarm_mask; - gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -291,7 +293,7 @@ - int regvalue; - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[1] = FAN_TO_REG(val, - DIV_FROM_REG(data->fan_div[1])); -@@ -306,7 +308,7 @@ - data->beep_mask &= data->alarm_mask; - gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -343,13 +345,6 @@ - * Real code - */ - --static int gl518_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, gl518_detect); --} -- - static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) - { - int i; -@@ -407,7 +402,7 @@ - strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -525,7 +520,7 @@ - struct gl518_data *data = i2c_get_clientdata(client); - int val; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -586,7 +581,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/gl520sm.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/gl520sm.c 2006-03-22 17:06:16.000000000 +0100 -@@ -29,6 +29,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Type of the extra sensor */ - static unsigned short extra_sensor_type; -@@ -99,7 +100,6 @@ - * Function declarations - */ - --static int gl520_attach_adapter(struct i2c_adapter *adapter); - static int gl520_detect(struct i2c_adapter *adapter, int address, int kind); - static void gl520_init_client(struct i2c_client *client); - static int gl520_detach_client(struct i2c_client *client); -@@ -113,7 +113,9 @@ - .name = "gl520sm", - }, - .id = I2C_DRIVERID_GL520, -- .attach_adapter = gl520_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = gl520_detect, - .detach_client = gl520_detach_client, - }; - -@@ -121,7 +123,7 @@ - struct gl520_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until the following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -303,7 +305,7 @@ - long v = simple_strtol(buf, NULL, 10); - u8 r; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (n == 0) - r = VDD_TO_REG(v); -@@ -317,7 +319,7 @@ - else - gl520_write_value(client, reg, r); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -331,7 +333,7 @@ - else - r = IN_TO_REG(v); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - data->in_max[n] = r; - -@@ -340,7 +342,7 @@ - else - gl520_write_value(client, reg, r); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -373,7 +375,7 @@ - unsigned long v = simple_strtoul(buf, NULL, 10); - u8 r; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - r = FAN_TO_REG(v, data->fan_div[n - 1]); - data->fan_min[n - 1] = r; - -@@ -390,7 +392,7 @@ - data->beep_mask &= data->alarm_mask; - gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -409,7 +411,7 @@ - return -EINVAL; - } - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_div[n - 1] = r; - - if (n == 1) -@@ -417,7 +419,7 @@ - else - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -425,10 +427,10 @@ - { - u8 r = simple_strtoul(buf, NULL, 10)?1:0; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_off = r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -454,10 +456,10 @@ - { - long v = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[n - 1] = TEMP_TO_REG(v);; - gl520_write_value(client, reg, data->temp_max[n - 1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -465,10 +467,10 @@ - { - long v = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); - gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -491,10 +493,10 @@ - { - u8 r = simple_strtoul(buf, NULL, 10)?0:1; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->beep_enable = !r; - gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -502,11 +504,11 @@ - { - u8 r = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - r &= data->alarm_mask; - data->beep_mask = r; - gl520_write_value(client, reg, r); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -515,13 +517,6 @@ - * Real code - */ - --static int gl520_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, gl520_detect); --} -- - static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) - { - struct i2c_client *new_client; -@@ -561,7 +556,7 @@ - /* Fill in the remaining client fields */ - strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -685,7 +680,7 @@ - struct gl520_data *data = i2c_get_clientdata(client); - int val; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - -@@ -750,7 +745,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/hdaps.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/hdaps.c 2006-03-22 17:06:15.000000000 +0100 -@@ -33,6 +33,7 @@ - #include <linux/module.h> - #include <linux/timer.h> - #include <linux/dmi.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ -@@ -70,10 +71,10 @@ - static int rest_x; - static int rest_y; - --static DECLARE_MUTEX(hdaps_sem); -+static DEFINE_MUTEX(hdaps_mutex); - - /* -- * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. -+ * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex. - */ - static inline u8 __get_latch(u16 port) - { -@@ -82,7 +83,7 @@ - - /* - * __check_latch - Check a port latch for a given value. Returns zero if the -- * port contains the given value. Callers must hold hdaps_sem. -+ * port contains the given value. Callers must hold hdaps_mutex. - */ - static inline int __check_latch(u16 port, u8 val) - { -@@ -93,7 +94,7 @@ - - /* - * __wait_latch - Wait up to 100us for a port latch to get a certain value, -- * returning zero if the value is obtained. Callers must hold hdaps_sem. -+ * returning zero if the value is obtained. Callers must hold hdaps_mutex. - */ - static int __wait_latch(u16 port, u8 val) - { -@@ -110,7 +111,7 @@ - - /* - * __device_refresh - request a refresh from the accelerometer. Does not wait -- * for refresh to complete. Callers must hold hdaps_sem. -+ * for refresh to complete. Callers must hold hdaps_mutex. - */ - static void __device_refresh(void) - { -@@ -124,7 +125,7 @@ - /* - * __device_refresh_sync - request a synchronous refresh from the - * accelerometer. We wait for the refresh to complete. Returns zero if -- * successful and nonzero on error. Callers must hold hdaps_sem. -+ * successful and nonzero on error. Callers must hold hdaps_mutex. - */ - static int __device_refresh_sync(void) - { -@@ -134,7 +135,7 @@ - - /* - * __device_complete - indicate to the accelerometer that we are done reading -- * data, and then initiate an async refresh. Callers must hold hdaps_sem. -+ * data, and then initiate an async refresh. Callers must hold hdaps_mutex. - */ - static inline void __device_complete(void) - { -@@ -152,7 +153,7 @@ - { - int ret; - -- down(&hdaps_sem); -+ mutex_lock(&hdaps_mutex); - - /* do a sync refresh -- we need to be sure that we read fresh data */ - ret = __device_refresh_sync(); -@@ -163,7 +164,7 @@ - __device_complete(); - - out: -- up(&hdaps_sem); -+ mutex_unlock(&hdaps_mutex); - return ret; - } - -@@ -198,9 +199,9 @@ - { - int ret; - -- down(&hdaps_sem); -+ mutex_lock(&hdaps_mutex); - ret = __hdaps_read_pair(port1, port2, val1, val2); -- up(&hdaps_sem); -+ mutex_unlock(&hdaps_mutex); - - return ret; - } -@@ -213,7 +214,7 @@ - { - int total, ret = -ENXIO; - -- down(&hdaps_sem); -+ mutex_lock(&hdaps_mutex); - - outb(0x13, 0x1610); - outb(0x01, 0x161f); -@@ -279,7 +280,7 @@ - } - - out: -- up(&hdaps_sem); -+ mutex_unlock(&hdaps_mutex); - return ret; - } - -@@ -313,7 +314,7 @@ - }; - - /* -- * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. -+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex. - */ - static void hdaps_calibrate(void) - { -@@ -325,7 +326,7 @@ - int x, y; - - /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ -- if (down_trylock(&hdaps_sem)) { -+ if (!mutex_trylock(&hdaps_mutex)) { - mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); - return; - } -@@ -340,7 +341,7 @@ - mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); - - out: -- up(&hdaps_sem); -+ mutex_unlock(&hdaps_mutex); - } - - -@@ -420,9 +421,9 @@ - struct device_attribute *attr, - const char *buf, size_t count) - { -- down(&hdaps_sem); -+ mutex_lock(&hdaps_mutex); - hdaps_calibrate(); -- up(&hdaps_sem); -+ mutex_unlock(&hdaps_mutex); - - return count; - } ---- linux-2.6.16.orig/drivers/hwmon/it87.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/it87.c 2006-03-22 17:06:16.000000000 +0100 -@@ -41,6 +41,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - -@@ -194,10 +195,10 @@ - struct it87_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -219,14 +220,12 @@ - }; - - --static int it87_attach_adapter(struct i2c_adapter *adapter); - static int it87_isa_attach_adapter(struct i2c_adapter *adapter); - static int it87_detect(struct i2c_adapter *adapter, int address, int kind); - static int it87_detach_client(struct i2c_client *client); - --static int it87_read_value(struct i2c_client *client, u8 register); --static int it87_write_value(struct i2c_client *client, u8 register, -- u8 value); -+static int it87_read_value(struct i2c_client *client, u8 reg); -+static int it87_write_value(struct i2c_client *client, u8 reg, u8 value); - static struct it87_data *it87_update_device(struct device *dev); - static int it87_check_pwm(struct i2c_client *client); - static void it87_init_client(struct i2c_client *client, struct it87_data *data); -@@ -237,7 +236,9 @@ - .name = "it87", - }, - .id = I2C_DRIVERID_IT87, -- .attach_adapter = it87_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = it87_detect, - .detach_client = it87_detach_client, - }; - -@@ -290,11 +291,11 @@ - struct it87_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - it87_write_value(client, IT87_REG_VIN_MIN(nr), - data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, -@@ -307,11 +308,11 @@ - struct it87_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - it87_write_value(client, IT87_REG_VIN_MAX(nr), - data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -381,10 +382,10 @@ - struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_high[nr] = TEMP_TO_REG(val); - it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, -@@ -397,10 +398,10 @@ - struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_low[nr] = TEMP_TO_REG(val); - it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_temp_offset(offset) \ -@@ -440,7 +441,7 @@ - struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - data->sensor &= ~(1 << nr); - data->sensor &= ~(8 << nr); -@@ -450,11 +451,11 @@ - else if (val == 2) - data->sensor |= 8 << nr; - else if (val != 0) { -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_sensor_offset(offset) \ -@@ -524,7 +525,7 @@ - int val = simple_strtol(buf, NULL, 10); - u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - switch (nr) { - case 0: data->fan_div[nr] = reg & 0x07; break; - case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; -@@ -533,7 +534,7 @@ - - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, -@@ -548,7 +549,7 @@ - int i, min[3]; - u8 old; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - old = it87_read_value(client, IT87_REG_FAN_DIV); - - for (i = 0; i < 3; i++) -@@ -576,7 +577,7 @@ - data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); - it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_pwm_enable(struct device *dev, -@@ -589,7 +590,7 @@ - struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (val == 0) { - int tmp; -@@ -606,11 +607,11 @@ - /* set saved pwm value, clear FAN_CTLX PWM mode bit */ - it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); - } else { -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, -@@ -626,11 +627,11 @@ - if (val < 0 || val > 255) - return -EINVAL; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->manual_pwm_ctl[nr] = val; - if (data->fan_main_ctrl & (1 << nr)) - it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -696,17 +697,6 @@ - #define device_create_file_vid(client) \ - device_create_file(&client->dev, &dev_attr_cpu0_vid) - --/* This function is called when: -- * it87_driver is inserted (when this module is loaded), for each -- available adapter -- * when a new adapter is inserted (and it87_driver is still present) */ --static int it87_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, it87_detect); --} -- - static int it87_isa_attach_adapter(struct i2c_adapter *adapter) - { - return it87_detect(adapter, isa_address, -1); -@@ -776,7 +766,7 @@ - - new_client = &data->client; - if (is_isa) -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; -@@ -823,7 +813,7 @@ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -950,10 +940,10 @@ - - int res; - if (i2c_is_isa_client(client)) { -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - res = inb_p(client->addr + IT87_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } else - return i2c_smbus_read_byte_data(client, reg); -@@ -969,10 +959,10 @@ - struct it87_data *data = i2c_get_clientdata(client); - - if (i2c_is_isa_client(client)) { -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - outb_p(value, client->addr + IT87_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } else - return i2c_smbus_write_byte_data(client, reg, value); -@@ -1098,7 +1088,7 @@ - struct it87_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -1160,7 +1150,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm63.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm63.c 2006-03-22 17:06:16.000000000 +0100 -@@ -45,6 +45,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -126,7 +127,6 @@ - * Functions declaration - */ - --static int lm63_attach_adapter(struct i2c_adapter *adapter); - static int lm63_detach_client(struct i2c_client *client); - - static struct lm63_data *lm63_update_device(struct device *dev); -@@ -142,7 +142,9 @@ - .driver = { - .name = "lm63", - }, -- .attach_adapter = lm63_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm63_detect, - .detach_client = lm63_detach_client, - }; - -@@ -153,7 +155,7 @@ - struct lm63_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -192,13 +194,13 @@ - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan[1] = FAN_TO_REG(val); - i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, - data->fan[1] & 0xFF); - i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, - data->fan[1] >> 8); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -222,12 +224,12 @@ - return -EPERM; - - val = simple_strtoul(buf, NULL, 10); -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm1_value = val <= 0 ? 0 : - val >= 255 ? 2 * data->pwm1_freq : - (val * data->pwm1_freq * 2 + 127) / 255; - i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -253,10 +255,10 @@ - struct lm63_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp8[1] = TEMP8_TO_REG(val); - i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -284,13 +286,13 @@ - long val = simple_strtol(buf, NULL, 10); - int nr = attr->index; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp11[nr] = TEMP11_TO_REG(val); - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], - data->temp11[nr] >> 8); - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], - data->temp11[nr] & 0xff); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -314,11 +316,11 @@ - long val = simple_strtol(buf, NULL, 10); - long hyst; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - hyst = TEMP8_FROM_REG(data->temp8[2]) - val; - i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, - HYST_TO_REG(hyst)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -329,9 +331,19 @@ - return sprintf(buf, "%u\n", data->alarms); - } - -+static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr, -+ char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ struct lm63_data *data = lm63_update_device(dev); -+ -+ return sprintf(buf, "%u\n", (data->alarms >> attr->index) & 1); -+} -+ - static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); - static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, - set_fan, 1); -+static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); - - static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); - static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); -@@ -339,13 +351,18 @@ - static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); - static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 1); -+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); - - static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); -+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); - static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 1); -+static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); - static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 2); -+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); - static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); -+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); - static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, - set_temp2_crit_hyst); - -@@ -355,13 +372,6 @@ - * Real code - */ - --static int lm63_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm63_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -427,7 +437,7 @@ - - strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -448,6 +458,8 @@ - &sensor_dev_attr_fan1_input.dev_attr); - device_create_file(&new_client->dev, - &sensor_dev_attr_fan1_min.dev_attr); -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_fan1_min_alarm.dev_attr); - } - device_create_file(&new_client->dev, &dev_attr_pwm1); - device_create_file(&new_client->dev, &dev_attr_pwm1_enable); -@@ -456,13 +468,23 @@ - device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_input_fault.dev_attr); -+ device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_min.dev_attr); - device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_min_alarm.dev_attr); -+ device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp1_max_alarm.dev_attr); -+ device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_max.dev_attr); - device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_max_alarm.dev_attr); -+ device_create_file(&new_client->dev, - &sensor_dev_attr_temp2_crit.dev_attr); -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_crit_alarm.dev_attr); - device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); - device_create_file(&new_client->dev, &dev_attr_alarms); - -@@ -530,7 +552,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - if (data->config & 0x04) { /* tachometer enabled */ -@@ -582,7 +604,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm75.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm75.c 2006-03-22 17:06:16.000000000 +0100 -@@ -25,6 +25,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include "lm75.h" - - -@@ -47,7 +48,7 @@ - struct lm75_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - u16 temp_input; /* Register values */ -@@ -55,7 +56,6 @@ - u16 temp_hyst; - }; - --static int lm75_attach_adapter(struct i2c_adapter *adapter); - 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); -@@ -70,7 +70,9 @@ - .name = "lm75", - }, - .id = I2C_DRIVERID_LM75, -- .attach_adapter = lm75_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm75_detect, - .detach_client = lm75_detach_client, - }; - -@@ -91,10 +93,10 @@ - struct lm75_data *data = i2c_get_clientdata(client); \ - int temp = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = LM75_TEMP_TO_REG(temp); \ - lm75_write_value(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - set(temp_max, LM75_REG_TEMP_OS); -@@ -104,13 +106,6 @@ - static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); - static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); - --static int lm75_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm75_detect); --} -- - /* This function is called by i2c_probe */ - static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) - { -@@ -188,7 +183,7 @@ - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -264,7 +259,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm75_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -277,7 +272,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm77.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm77.c 2006-03-22 17:06:16.000000000 +0100 -@@ -32,6 +32,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; -@@ -51,7 +52,7 @@ - struct lm77_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; - unsigned long last_updated; /* In jiffies */ - int temp_input; /* Temperatures */ -@@ -62,7 +63,6 @@ - u8 alarms; - }; - --static int lm77_attach_adapter(struct i2c_adapter *adapter); - static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); - static void lm77_init_client(struct i2c_client *client); - static int lm77_detach_client(struct i2c_client *client); -@@ -77,7 +77,9 @@ - .driver = { - .name = "lm77", - }, -- .attach_adapter = lm77_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm77_detect, - .detach_client = lm77_detach_client, - }; - -@@ -139,10 +141,10 @@ - struct lm77_data *data = i2c_get_clientdata(client); \ - long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = val; \ - lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -157,11 +159,11 @@ - struct lm77_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_hyst = data->temp_crit - val; - lm77_write_value(client, LM77_REG_TEMP_HYST, - LM77_TEMP_TO_REG(data->temp_hyst)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -173,7 +175,7 @@ - long val = simple_strtoul(buf, NULL, 10); - int oldcrithyst; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - oldcrithyst = data->temp_crit - data->temp_hyst; - data->temp_crit = val; - data->temp_hyst = data->temp_crit - oldcrithyst; -@@ -181,7 +183,7 @@ - LM77_TEMP_TO_REG(data->temp_crit)); - lm77_write_value(client, LM77_REG_TEMP_HYST, - LM77_TEMP_TO_REG(data->temp_hyst)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -204,13 +206,6 @@ - static DEVICE_ATTR(alarms, S_IRUGO, - show_alarms, NULL); - --static int lm77_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm77_detect); --} -- - /* This function is called by i2c_probe */ - static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) - { -@@ -306,7 +301,7 @@ - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -380,7 +375,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm77_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -406,7 +401,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm78.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm78.c 2006-03-22 17:06:16.000000000 +0100 -@@ -27,6 +27,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - /* Addresses to scan */ -@@ -131,10 +132,10 @@ - struct lm78_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -152,13 +153,12 @@ - }; - - --static int lm78_attach_adapter(struct i2c_adapter *adapter); - static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); - static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); - static int lm78_detach_client(struct i2c_client *client); - --static int lm78_read_value(struct i2c_client *client, u8 register); --static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); -+static int lm78_read_value(struct i2c_client *client, u8 reg); -+static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); - static struct lm78_data *lm78_update_device(struct device *dev); - static void lm78_init_client(struct i2c_client *client); - -@@ -168,7 +168,9 @@ - .name = "lm78", - }, - .id = I2C_DRIVERID_LM78, -- .attach_adapter = lm78_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm78_detect, - .detach_client = lm78_detach_client, - }; - -@@ -207,10 +209,10 @@ - struct lm78_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -221,10 +223,10 @@ - struct lm78_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -288,10 +290,10 @@ - struct lm78_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_over = TEMP_TO_REG(val); - lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -307,10 +309,10 @@ - struct lm78_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_hyst = TEMP_TO_REG(val); - lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -342,10 +344,10 @@ - struct lm78_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -368,7 +370,7 @@ - unsigned long min; - u8 reg; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - -@@ -380,7 +382,7 @@ - default: - dev_err(&client->dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -398,7 +400,7 @@ - data->fan_min[nr] = - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -464,17 +466,6 @@ - } - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - --/* This function is called when: -- * lm78_driver is inserted (when this module is loaded), for each -- available adapter -- * when a new adapter is inserted (and lm78_driver is still present) */ --static int lm78_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm78_detect); --} -- - static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) - { - return lm78_detect(adapter, isa_address, -1); -@@ -548,7 +539,7 @@ - - new_client = &data->client; - if (is_isa) -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; -@@ -598,7 +589,7 @@ - data->type = kind; - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -697,10 +688,10 @@ - int res; - if (i2c_is_isa_client(client)) { - struct lm78_data *data = i2c_get_clientdata(client); -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); - res = inb_p(client->addr + LM78_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } else - return i2c_smbus_read_byte_data(client, reg); -@@ -717,10 +708,10 @@ - { - if (i2c_is_isa_client(client)) { - struct lm78_data *data = i2c_get_clientdata(client); -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); - outb_p(value, client->addr + LM78_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } else - return i2c_smbus_write_byte_data(client, reg, value); -@@ -742,7 +733,7 @@ - struct lm78_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -786,7 +777,7 @@ - data->fan_div[2] = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm80.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm80.c 2006-03-22 17:06:16.000000000 +0100 -@@ -28,6 +28,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, -@@ -108,7 +109,7 @@ - struct lm80_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -130,7 +131,6 @@ - * Functions declaration - */ - --static int lm80_attach_adapter(struct i2c_adapter *adapter); - static int lm80_detect(struct i2c_adapter *adapter, int address, int kind); - static void lm80_init_client(struct i2c_client *client); - static int lm80_detach_client(struct i2c_client *client); -@@ -147,7 +147,9 @@ - .name = "lm80", - }, - .id = I2C_DRIVERID_LM80, -- .attach_adapter = lm80_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm80_detect, - .detach_client = lm80_detach_client, - }; - -@@ -191,10 +193,10 @@ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock);\ -+ mutex_lock(&data->update_lock);\ - data->value = IN_TO_REG(val); \ - lm80_write_value(client, reg, data->value); \ -- up(&data->update_lock);\ -+ mutex_unlock(&data->update_lock);\ - return count; \ - } - set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); -@@ -241,10 +243,10 @@ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock);\ -+ mutex_lock(&data->update_lock);\ - data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ - lm80_write_value(client, reg, data->value); \ -- up(&data->update_lock);\ -+ mutex_unlock(&data->update_lock);\ - return count; \ - } - set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); -@@ -263,7 +265,7 @@ - u8 reg; - - /* Save fan_min */ -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - -@@ -275,7 +277,7 @@ - default: - dev_err(&client->dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -286,7 +288,7 @@ - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -325,10 +327,10 @@ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = TEMP_LIMIT_TO_REG(val); \ - lm80_write_value(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); -@@ -386,13 +388,6 @@ - * Real code - */ - --static int lm80_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm80_detect); --} -- - static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) - { - int i, cur; -@@ -437,7 +432,7 @@ - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -545,7 +540,7 @@ - struct lm80_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - dev_dbg(&client->dev, "Starting lm80 update\n"); -@@ -585,7 +580,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm83.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm83.c 2006-03-22 17:06:16.000000000 +0100 -@@ -12,6 +12,10 @@ - * Since the datasheet omits to give the chip stepping code, I give it - * here: 0x03 (at register 0xff). - * -+ * Also supports the LM82 temp sensor, which is basically a stripped down -+ * model of the LM83. Datasheet is here: -+ * http://www.national.com/pf/LM/LM82.html -+ * - * 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 -@@ -35,6 +39,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -51,7 +56,7 @@ - * Insmod parameters - */ - --I2C_CLIENT_INSMOD_1(lm83); -+I2C_CLIENT_INSMOD_2(lm83, lm82); - - /* - * The LM83 registers -@@ -114,7 +119,6 @@ - * Functions declaration - */ - --static int lm83_attach_adapter(struct i2c_adapter *adapter); - static int lm83_detect(struct i2c_adapter *adapter, int address, int kind); - static int lm83_detach_client(struct i2c_client *client); - static struct lm83_data *lm83_update_device(struct device *dev); -@@ -128,7 +132,9 @@ - .name = "lm83", - }, - .id = I2C_DRIVERID_LM83, -- .attach_adapter = lm83_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm83_detect, - .detach_client = lm83_detach_client, - }; - -@@ -139,7 +145,7 @@ - struct lm83_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -171,11 +177,11 @@ - long val = simple_strtol(buf, NULL, 10); - int nr = attr->index; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp[nr] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], - data->temp[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -209,13 +215,6 @@ - * Real code - */ - --static int lm83_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm83_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -282,6 +281,9 @@ - if (man_id == 0x01) { /* National Semiconductor */ - if (chip_id == 0x03) { - kind = lm83; -+ } else -+ if (chip_id == 0x01) { -+ kind = lm82; - } - } - -@@ -295,12 +297,15 @@ - - if (kind == lm83) { - name = "lm83"; -+ } else -+ if (kind == lm82) { -+ name = "lm82"; - } - - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -318,32 +323,46 @@ - goto exit_detach; - } - -+ /* -+ * The LM82 can only monitor one external diode which is -+ * at the same register as the LM83 temp3 entry - so we -+ * declare 1 and 3 common, and then 2 and 4 only for the LM83. -+ */ -+ - device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_input.dev_attr); -- device_create_file(&new_client->dev, - &sensor_dev_attr_temp3_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp4_input.dev_attr); -+ - device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_max.dev_attr); - device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_max.dev_attr); -- device_create_file(&new_client->dev, - &sensor_dev_attr_temp3_max.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp4_max.dev_attr); -+ - device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_crit.dev_attr); - device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_crit.dev_attr); -- device_create_file(&new_client->dev, - &sensor_dev_attr_temp3_crit.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp4_crit.dev_attr); -+ - device_create_file(&new_client->dev, &dev_attr_alarms); - -+ if (kind == lm83) { -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_input.dev_attr); -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp4_input.dev_attr); -+ -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_max.dev_attr); -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp4_max.dev_attr); -+ -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp2_crit.dev_attr); -+ device_create_file(&new_client->dev, -+ &sensor_dev_attr_temp4_crit.dev_attr); -+ } -+ - return 0; - - exit_detach: -@@ -373,7 +392,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm83_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - int nr; -@@ -393,7 +412,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm85.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm85.c 2006-03-22 17:06:16.000000000 +0100 -@@ -31,6 +31,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* Addresses to scan */ - static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; -@@ -331,10 +332,10 @@ - struct lm85_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_reading; /* In jiffies */ - unsigned long last_config; /* In jiffies */ -@@ -368,13 +369,12 @@ - struct lm85_zone zone[3]; - }; - --static int lm85_attach_adapter(struct i2c_adapter *adapter); - static int lm85_detect(struct i2c_adapter *adapter, int address, - int kind); - static int lm85_detach_client(struct i2c_client *client); - --static int lm85_read_value(struct i2c_client *client, u8 register); --static int lm85_write_value(struct i2c_client *client, u8 register, int value); -+static int lm85_read_value(struct i2c_client *client, u8 reg); -+static int lm85_write_value(struct i2c_client *client, u8 reg, int value); - static struct lm85_data *lm85_update_device(struct device *dev); - static void lm85_init_client(struct i2c_client *client); - -@@ -384,7 +384,9 @@ - .name = "lm85", - }, - .id = I2C_DRIVERID_LM85, -- .attach_adapter = lm85_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm85_detect, - .detach_client = lm85_detach_client, - }; - -@@ -407,10 +409,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val); - lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -499,10 +501,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[nr] = PWM_TO_REG(val); - lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) -@@ -559,10 +561,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = INS_TO_REG(nr, val); - lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_in_max(struct device *dev, char *buf, int nr) -@@ -577,10 +579,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = INS_TO_REG(nr, val); - lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_in_reg(offset) \ -@@ -640,10 +642,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_temp_max(struct device *dev, char *buf, int nr) -@@ -658,10 +660,10 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_temp_reg(offset) \ -@@ -713,12 +715,12 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) - | ZONE_TO_REG(val) ; - lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), - data->autofan[nr].config); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) -@@ -733,11 +735,11 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->autofan[nr].min_pwm = PWM_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), - data->autofan[nr].min_pwm); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) -@@ -752,7 +754,7 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->autofan[nr].min_off = val; - lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] - | data->syncpwm3 -@@ -760,7 +762,7 @@ - | (data->autofan[1].min_off ? 0x40 : 0) - | (data->autofan[2].min_off ? 0x80 : 0) - ); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) -@@ -775,13 +777,13 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->autofan[nr].freq = FREQ_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), - (data->zone[nr].range << 4) - | data->autofan[nr].freq - ); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define pwm_auto(offset) \ -@@ -857,7 +859,7 @@ - int min; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = TEMP_FROM_REG(data->zone[nr].limit); - data->zone[nr].off_desired = TEMP_TO_REG(val); - data->zone[nr].hyst = HYST_TO_REG(min - val); -@@ -871,7 +873,7 @@ - (data->zone[2].hyst << 4) - ); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) -@@ -886,7 +888,7 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->zone[nr].limit = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), - data->zone[nr].limit); -@@ -913,7 +915,7 @@ - (data->zone[2].hyst << 4) - ); - } -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) -@@ -930,7 +932,7 @@ - int min; - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = TEMP_FROM_REG(data->zone[nr].limit); - data->zone[nr].max_desired = TEMP_TO_REG(val); - data->zone[nr].range = RANGE_TO_REG( -@@ -938,7 +940,7 @@ - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), - ((data->zone[nr].range & 0x0f) << 4) - | (data->autofan[nr].freq & 0x07)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) -@@ -953,11 +955,11 @@ - struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->zone[nr].critical = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), - data->zone[nr].critical); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define temp_auto(offset) \ -@@ -1017,13 +1019,6 @@ - temp_auto(2); - temp_auto(3); - --static int lm85_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm85_detect); --} -- - static int lm85_detect(struct i2c_adapter *adapter, int address, - int kind) - { -@@ -1149,7 +1144,7 @@ - /* Fill in the remaining client fields */ - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -1368,7 +1363,7 @@ - struct lm85_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if ( !data->valid || - time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) { -@@ -1571,7 +1566,7 @@ - - data->valid = 1; - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm87.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm87.c 2006-03-22 17:06:16.000000000 +0100 -@@ -60,6 +60,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -150,7 +151,6 @@ - * Functions declaration - */ - --static int lm87_attach_adapter(struct i2c_adapter *adapter); - static int lm87_detect(struct i2c_adapter *adapter, int address, int kind); - static void lm87_init_client(struct i2c_client *client); - static int lm87_detach_client(struct i2c_client *client); -@@ -165,7 +165,9 @@ - .name = "lm87", - }, - .id = I2C_DRIVERID_LM87, -- .attach_adapter = lm87_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm87_detect, - .detach_client = lm87_detach_client, - }; - -@@ -176,7 +178,7 @@ - struct lm87_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -253,11 +255,11 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); - lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) : - LM87_REG_AIN_MIN(nr-6), data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - static void set_in_max(struct device *dev, const char *buf, int nr) -@@ -266,11 +268,11 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); - lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) : - LM87_REG_AIN_MAX(nr-6), data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - #define set_in(offset) \ -@@ -327,10 +329,10 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_low[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - static void set_temp_high(struct device *dev, const char *buf, int nr) -@@ -339,10 +341,10 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_high[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - #define set_temp(offset) \ -@@ -411,11 +413,11 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, - FAN_DIV_FROM_REG(data->fan_div[nr])); - lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - } - - /* Note: we save and restore the fan minimum here, because its value is -@@ -431,7 +433,7 @@ - unsigned long min; - u8 reg; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - FAN_DIV_FROM_REG(data->fan_div[nr])); - -@@ -441,7 +443,7 @@ - case 4: data->fan_div[nr] = 2; break; - case 8: data->fan_div[nr] = 3; break; - default: -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -459,7 +461,7 @@ - data->fan_min[nr] = FAN_TO_REG(min, val); - lm87_write_value(client, LM87_REG_FAN_MIN(nr), - data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -522,10 +524,10 @@ - struct lm87_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->aout = AOUT_TO_REG(val); - lm87_write_value(client, LM87_REG_AOUT, data->aout); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); -@@ -534,13 +536,6 @@ - * Real code - */ - --static int lm87_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm87_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -589,7 +584,7 @@ - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -744,7 +739,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i, j; -@@ -813,7 +808,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm90.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm90.c 2006-03-22 17:06:16.000000000 +0100 -@@ -78,6 +78,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* - * Addresses to scan -@@ -174,7 +175,6 @@ - * Functions declaration - */ - --static int lm90_attach_adapter(struct i2c_adapter *adapter); - static int lm90_detect(struct i2c_adapter *adapter, int address, - int kind); - static void lm90_init_client(struct i2c_client *client); -@@ -190,7 +190,9 @@ - .name = "lm90", - }, - .id = I2C_DRIVERID_LM90, -- .attach_adapter = lm90_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm90_detect, - .detach_client = lm90_detach_client, - }; - -@@ -201,7 +203,7 @@ - struct lm90_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - int kind; -@@ -247,13 +249,13 @@ - long val = simple_strtol(buf, NULL, 10); - int nr = attr->index; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (data->kind == adt7461) - data->temp8[nr] = TEMP1_TO_REG_ADT7461(val); - else - data->temp8[nr] = TEMP1_TO_REG(val); - i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -281,7 +283,7 @@ - long val = simple_strtol(buf, NULL, 10); - int nr = attr->index; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (data->kind == adt7461) - data->temp11[nr] = TEMP2_TO_REG_ADT7461(val); - else -@@ -290,7 +292,7 @@ - data->temp11[nr] >> 8); - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], - data->temp11[nr] & 0xff); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -311,11 +313,11 @@ - long val = simple_strtol(buf, NULL, 10); - long hyst; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - hyst = TEMP1_FROM_REG(data->temp8[3]) - val; - i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, - HYST_TO_REG(hyst)); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -326,23 +328,42 @@ - return sprintf(buf, "%d\n", data->alarms); - } - --static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); --static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); --static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, -- set_temp8, 1); --static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, -- set_temp11, 1); --static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, -- set_temp8, 2); --static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, -- set_temp11, 2); --static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, -- set_temp8, 3); --static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, -- set_temp8, 4); --static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, -- set_temphyst, 3); --static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); -+static ssize_t show_alarm(struct device *dev, struct device_attribute -+ *devattr, char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ struct lm90_data *data = lm90_update_device(dev); -+ -+ return sprintf(buf, "%d\n", (data->alarms >> attr->index) & 1); -+} -+ -+static struct sensor_device_attribute lm90_sensor_attr[] = { -+ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0), -+ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0), -+ SENSOR_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2), -+ SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, -+ set_temp8, 1), -+ SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5), -+ SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, -+ set_temp11, 1), -+ SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3), -+ SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, -+ set_temp8, 2), -+ SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6), -+ SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, -+ set_temp11, 2), -+ SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4), -+ SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, -+ set_temp8, 3), -+ SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0), -+ SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, -+ set_temp8, 4), -+ SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1), -+ SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, -+ set_temphyst, 3), -+ SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4), -+}; -+ - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - - /* pec used for ADM1032 only */ -@@ -413,13 +434,6 @@ - return 0; - } - --static int lm90_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm90_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -428,7 +442,7 @@ - { - struct i2c_client *new_client; - struct lm90_data *data; -- int err = 0; -+ int i, err = 0; - const char *name = ""; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -@@ -558,7 +572,7 @@ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; - data->kind = kind; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -574,26 +588,13 @@ - goto exit_detach; - } - -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp1_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_input.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp1_min.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_min.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp1_max.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_max.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp1_crit.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_crit.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp1_crit_hyst.dev_attr); -- device_create_file(&new_client->dev, -- &sensor_dev_attr_temp2_crit_hyst.dev_attr); -+ for (i = 0; i < ARRAY_SIZE(lm90_sensor_attr); i++) { -+ err = device_create_file(&new_client->dev, -+ &lm90_sensor_attr[i].dev_attr); -+ if (err) -+ goto exit_class; -+ } -+ - device_create_file(&new_client->dev, &dev_attr_alarms); - - if (new_client->flags & I2C_CLIENT_PEC) -@@ -601,6 +602,9 @@ - - return 0; - -+exit_class: -+ dev_err(&new_client->dev, "Sysfs interface creation failed\n"); -+ hwmon_device_unregister(data->class_dev); - exit_detach: - i2c_detach_client(new_client); - exit_free: -@@ -646,7 +650,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - u8 oldh, newh, l; -@@ -692,7 +696,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/lm92.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/lm92.c 2006-03-22 17:06:16.000000000 +0100 -@@ -46,6 +46,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* The LM92 and MAX6635 have 2 two-state pins for address selection, - resulting in 4 possible addresses. */ -@@ -96,7 +97,7 @@ - struct lm92_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -114,7 +115,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct lm92_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) - || !data->valid) { -@@ -134,7 +135,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } -@@ -158,10 +159,10 @@ - struct lm92_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(val); \ - i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - set_temp(temp1_crit, LM92_REG_TEMP_CRIT); -@@ -194,11 +195,11 @@ - struct lm92_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; - i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, - swab16(TEMP_TO_REG(data->temp1_hyst))); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -348,7 +349,7 @@ - /* Fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the i2c subsystem a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -383,13 +384,6 @@ - return err; - } - --static int lm92_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, lm92_detect); --} -- - static int lm92_detach_client(struct i2c_client *client) - { - struct lm92_data *data = i2c_get_clientdata(client); -@@ -414,7 +408,9 @@ - .name = "lm92", - }, - .id = I2C_DRIVERID_LM92, -- .attach_adapter = lm92_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = lm92_detect, - .detach_client = lm92_detach_client, - }; - ---- linux-2.6.16.orig/drivers/hwmon/max1619.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/max1619.c 2006-03-22 17:06:16.000000000 +0100 -@@ -33,6 +33,7 @@ - #include <linux/i2c.h> - #include <linux/hwmon.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, - 0x29, 0x2a, 0x2b, -@@ -78,7 +79,6 @@ - * Functions declaration - */ - --static int max1619_attach_adapter(struct i2c_adapter *adapter); - static int max1619_detect(struct i2c_adapter *adapter, int address, - int kind); - static void max1619_init_client(struct i2c_client *client); -@@ -93,7 +93,9 @@ - .driver = { - .name = "max1619", - }, -- .attach_adapter = max1619_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = max1619_detect, - .detach_client = max1619_detach_client, - }; - -@@ -104,7 +106,7 @@ - struct max1619_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -141,10 +143,10 @@ - struct max1619_data *data = i2c_get_clientdata(client); \ - long val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(val); \ - i2c_smbus_write_byte_data(client, reg, data->value); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - -@@ -175,13 +177,6 @@ - * Real code - */ - --static int max1619_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, max1619_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -262,7 +257,7 @@ - /* We can fill in the remaining client fields */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -330,7 +325,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct max1619_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - dev_dbg(&client->dev, "Updating max1619 data.\n"); -@@ -353,7 +348,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/sis5595.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/sis5595.c 2006-03-22 17:06:15.000000000 +0100 -@@ -60,6 +60,7 @@ - #include <linux/err.h> - #include <linux/init.h> - #include <linux/jiffies.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - -@@ -167,9 +168,9 @@ - struct sis5595_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - char maxins; /* == 3 if temp enabled, otherwise == 4 */ -@@ -192,8 +193,8 @@ - static int sis5595_detect(struct i2c_adapter *adapter); - static int sis5595_detach_client(struct i2c_client *client); - --static int sis5595_read_value(struct i2c_client *client, u8 register); --static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value); -+static int sis5595_read_value(struct i2c_client *client, u8 reg); -+static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); - static struct sis5595_data *sis5595_update_device(struct device *dev); - static void sis5595_init_client(struct i2c_client *client); - -@@ -231,10 +232,10 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -245,10 +246,10 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -310,10 +311,10 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_over = TEMP_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -329,10 +330,10 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_hyst = TEMP_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -364,10 +365,10 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -390,7 +391,7 @@ - unsigned long val = simple_strtoul(buf, NULL, 10); - int reg; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - reg = sis5595_read_value(client, SIS5595_REG_FANDIV); -@@ -403,7 +404,7 @@ - default: - dev_err(&client->dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -419,7 +420,7 @@ - data->fan_min[nr] = - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -527,7 +528,7 @@ - - new_client = &data->client; - new_client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->adapter = adapter; - new_client->driver = &sis5595_driver; -@@ -548,7 +549,7 @@ - strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -635,20 +636,20 @@ - int res; - - struct sis5595_data *data = i2c_get_clientdata(client); -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); - res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } - - static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) - { - struct sis5595_data *data = i2c_get_clientdata(client); -- down(&data->lock); -+ mutex_lock(&data->lock); - outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); - outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } - -@@ -667,7 +668,7 @@ - struct sis5595_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -707,7 +708,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/smsc47b397.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/smsc47b397.c 2006-03-22 17:06:15.000000000 +0100 -@@ -35,6 +35,7 @@ - #include <linux/hwmon.h> - #include <linux/err.h> - #include <linux/init.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - /* Address is autodetected, there is no default value */ -@@ -92,9 +93,9 @@ - struct smsc47b397_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - -- struct semaphore update_lock; -+ struct mutex update_lock; - unsigned long last_updated; /* in jiffies */ - int valid; - -@@ -108,10 +109,10 @@ - struct smsc47b397_data *data = i2c_get_clientdata(client); - int res; - -- down(&data->lock); -+ mutex_lock(&data->lock); - outb(reg, client->addr); - res = inb_p(client->addr + 1); -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } - -@@ -121,7 +122,7 @@ - struct smsc47b397_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - dev_dbg(&client->dev, "starting device update...\n"); -@@ -144,7 +145,7 @@ - dev_dbg(&client->dev, "... device update complete\n"); - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } -@@ -254,14 +255,14 @@ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - new_client->adapter = adapter; - new_client->driver = &smsc47b397_driver; - new_client->flags = 0; - - strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); - -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - if ((err = i2c_attach_client(new_client))) - goto error_free; ---- linux-2.6.16.orig/drivers/hwmon/smsc47m1.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/smsc47m1.c 2006-03-22 17:06:15.000000000 +0100 -@@ -34,6 +34,7 @@ - #include <linux/hwmon.h> - #include <linux/err.h> - #include <linux/init.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - /* Address is autodetected, there is no default value */ -@@ -102,9 +103,9 @@ - struct smsc47m1_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - -- struct semaphore update_lock; -+ struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - - u8 fan[2]; /* Register value */ -@@ -188,18 +189,18 @@ - struct smsc47m1_data *data = i2c_get_clientdata(client); - long rpmdiv, val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); - - if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - - data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); - smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), - data->fan_preload[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -220,14 +221,14 @@ - if (new_div == old_div) /* No change */ - return count; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - switch (new_div) { - case 1: data->fan_div[nr] = 0; break; - case 2: data->fan_div[nr] = 1; break; - case 4: data->fan_div[nr] = 2; break; - case 8: data->fan_div[nr] = 3; break; - default: -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -241,7 +242,7 @@ - data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); - smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), - data->fan_preload[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -257,12 +258,12 @@ - if (val < 0 || val > 255) - return -EINVAL; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[nr] &= 0x81; /* Preserve additional bits */ - data->pwm[nr] |= PWM_TO_REG(val); - smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), - data->pwm[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -278,12 +279,12 @@ - if (val != 0 && val != 1) - return -EINVAL; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[nr] &= 0xFE; /* preserve the other bits */ - data->pwm[nr] |= !val; - smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), - data->pwm[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } -@@ -408,13 +409,13 @@ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - new_client->adapter = adapter; - new_client->driver = &smsc47m1_driver; - new_client->flags = 0; - - strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* If no function is properly configured, there's no point in - actually registering the chip. */ -@@ -512,17 +513,17 @@ - { - int res; - -- down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); -+ mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - res = inb_p(client->addr + reg); -- up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); -+ mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - return res; - } - - static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) - { -- down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); -+ mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - outb_p(value, client->addr + reg); -- up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); -+ mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - } - - static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, -@@ -531,7 +532,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m1_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { - int i; -@@ -558,7 +559,7 @@ - data->last_updated = jiffies; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return data; - } - ---- linux-2.6.16.orig/drivers/hwmon/via686a.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/via686a.c 2006-03-22 17:06:15.000000000 +0100 -@@ -39,6 +39,7 @@ - #include <linux/hwmon.h> - #include <linux/err.h> - #include <linux/init.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - -@@ -296,7 +297,7 @@ - struct via686a_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -355,11 +356,11 @@ - struct via686a_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val, nr); - via686a_write_value(client, VIA686A_REG_IN_MIN(nr), - data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_in_max(struct device *dev, const char *buf, -@@ -368,11 +369,11 @@ - struct via686a_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val, nr); - via686a_write_value(client, VIA686A_REG_IN_MAX(nr), - data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_in_offset(offset) \ -@@ -432,11 +433,11 @@ - struct via686a_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_over[nr] = TEMP_TO_REG(val); - via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], - data->temp_over[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp_hyst(struct device *dev, const char *buf, -@@ -445,11 +446,11 @@ - struct via686a_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_hyst[nr] = TEMP_TO_REG(val); - via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], - data->temp_hyst[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - #define show_temp_offset(offset) \ -@@ -508,10 +509,10 @@ - struct via686a_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_fan_div(struct device *dev, const char *buf, -@@ -521,12 +522,12 @@ - int val = simple_strtol(buf, NULL, 10); - int old; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - old = via686a_read_value(client, VIA686A_REG_FANDIV); - data->fan_div[nr] = DIV_TO_REG(val); - old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - via686a_write_value(client, VIA686A_REG_FANDIV, old); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -639,7 +640,7 @@ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; -@@ -733,7 +734,7 @@ - struct via686a_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -788,7 +789,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/vt8231.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/vt8231.c 2006-03-22 17:06:15.000000000 +0100 -@@ -35,6 +35,7 @@ - #include <linux/hwmon-sysfs.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - - static int force_addr; -@@ -148,7 +149,7 @@ - - struct vt8231_data { - struct i2c_client client; -- struct semaphore update_lock; -+ struct mutex update_lock; - struct class_device *class_dev; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ -@@ -223,10 +224,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -239,10 +240,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -281,11 +282,11 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, - 0, 255); - vt8231_write_value(client, regvoltmin[5], data->in_min[5]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -296,11 +297,11 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, - 0, 255); - vt8231_write_value(client, regvoltmax[5], data->in_max[5]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -351,10 +352,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(client, regtempmax[0], data->temp_max[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, -@@ -364,10 +365,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(client, regtempmin[0], data->temp_min[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -407,10 +408,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, -@@ -422,10 +423,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -520,10 +521,10 @@ - struct vt8231_data *data = i2c_get_clientdata(client); - int val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -539,7 +540,7 @@ - long min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - switch (val) { - case 1: data->fan_div[nr] = 0; break; - case 2: data->fan_div[nr] = 1; break; -@@ -548,7 +549,7 @@ - default: - dev_err(&client->dev, "fan_div value %ld not supported." - "Choose one of 1, 2, 4 or 8!\n", val); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -@@ -558,7 +559,7 @@ - - old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - vt8231_write_value(client, VT8231_REG_FANDIV, old); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -660,7 +661,7 @@ - /* Fill in the remaining client fields and put into the global list */ - strlcpy(client->name, "vt8231", I2C_NAME_SIZE); - -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) -@@ -745,7 +746,7 @@ - int i; - u16 low; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -804,7 +805,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/w83627ehf.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/w83627ehf.c 2006-03-22 17:06:16.000000000 +0100 -@@ -30,10 +30,7 @@ - Supports the following chips: - - Chip #vin #fan #pwm #temp chip_id man_id -- w83627ehf - 5 - 3 0x88 0x5ca3 -- -- This is a preliminary version of the driver, only supporting the -- fan and temperature inputs. The chip does much more than that. -+ w83627ehf 10 5 - 3 0x88 0x5ca3 - */ - - #include <linux/module.h> -@@ -42,7 +39,9 @@ - #include <linux/i2c.h> - #include <linux/i2c-isa.h> - #include <linux/hwmon.h> -+#include <linux/hwmon-sysfs.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - #include "lm75.h" - -@@ -119,6 +118,14 @@ - static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; - static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; - -+/* The W83627EHF registers for nr=7,8,9 are in bank 5 */ -+#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ -+ (0x554 + (((nr) - 7) * 2))) -+#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ -+ (0x555 + (((nr) - 7) * 2))) -+#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ -+ (0x550 + (nr) - 7)) -+ - #define W83627EHF_REG_TEMP1 0x27 - #define W83627EHF_REG_TEMP1_HYST 0x3a - #define W83627EHF_REG_TEMP1_OVER 0x39 -@@ -134,6 +141,10 @@ - #define W83627EHF_REG_DIODE 0x59 - #define W83627EHF_REG_SMI_OVT 0x4C - -+#define W83627EHF_REG_ALARM1 0x459 -+#define W83627EHF_REG_ALARM2 0x45A -+#define W83627EHF_REG_ALARM3 0x45B -+ - /* - * Conversions - */ -@@ -170,6 +181,20 @@ - return (temp + 500) / 1000; - } - -+/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ -+ -+static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 }; -+ -+static inline long in_from_reg(u8 reg, u8 nr) -+{ -+ return reg * scale_in[nr]; -+} -+ -+static inline u8 in_to_reg(u32 val, u8 nr) -+{ -+ return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255); -+} -+ - /* - * Data structures and manipulation thereof - */ -@@ -177,13 +202,16 @@ - struct w83627ehf_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* Register values */ -+ u8 in[10]; /* Register value */ -+ u8 in_max[10]; /* Register value */ -+ u8 in_min[10]; /* Register value */ - u8 fan[5]; - u8 fan_min[5]; - u8 fan_div[5]; -@@ -194,6 +222,7 @@ - s16 temp[2]; - s16 temp_max[2]; - s16 temp_max_hyst[2]; -+ u32 alarms; - }; - - static inline int is_word_sized(u16 reg) -@@ -230,7 +259,7 @@ - struct w83627ehf_data *data = i2c_get_clientdata(client); - int res, word_sized = is_word_sized(reg); - -- down(&data->lock); -+ mutex_lock(&data->lock); - - w83627ehf_set_bank(client, reg); - outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); -@@ -242,7 +271,7 @@ - } - w83627ehf_reset_bank(client, reg); - -- up(&data->lock); -+ mutex_unlock(&data->lock); - - return res; - } -@@ -252,7 +281,7 @@ - struct w83627ehf_data *data = i2c_get_clientdata(client); - int word_sized = is_word_sized(reg); - -- down(&data->lock); -+ mutex_lock(&data->lock); - - w83627ehf_set_bank(client, reg); - outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); -@@ -264,7 +293,7 @@ - outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); - w83627ehf_reset_bank(client, reg); - -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } - -@@ -322,7 +351,7 @@ - struct w83627ehf_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) - || !data->valid) { -@@ -347,6 +376,16 @@ - data->fan_div[3] |= (i >> 5) & 0x04; - } - -+ /* Measured voltages and limits */ -+ for (i = 0; i < 10; i++) { -+ data->in[i] = w83627ehf_read_value(client, -+ W83627EHF_REG_IN(i)); -+ data->in_min[i] = w83627ehf_read_value(client, -+ W83627EHF_REG_IN_MIN(i)); -+ data->in_max[i] = w83627ehf_read_value(client, -+ W83627EHF_REG_IN_MAX(i)); -+ } -+ - /* Measured fan speeds and limits */ - for (i = 0; i < 5; i++) { - if (!(data->has_fan & (1 << i))) -@@ -393,23 +432,136 @@ - W83627EHF_REG_TEMP_HYST[i]); - } - -+ data->alarms = w83627ehf_read_value(client, -+ W83627EHF_REG_ALARM1) | -+ (w83627ehf_read_value(client, -+ W83627EHF_REG_ALARM2) << 8) | -+ (w83627ehf_read_value(client, -+ W83627EHF_REG_ALARM3) << 16); -+ - data->last_updated = jiffies; - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return data; - } - - /* - * Sysfs callback functions - */ -+#define show_in_reg(reg) \ -+static ssize_t \ -+show_##reg(struct device *dev, struct device_attribute *attr, \ -+ char *buf) \ -+{ \ -+ struct w83627ehf_data *data = w83627ehf_update_device(dev); \ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ -+ int nr = sensor_attr->index; \ -+ return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], 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, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ struct i2c_client *client = to_i2c_client(dev); \ -+ struct w83627ehf_data *data = i2c_get_clientdata(client); \ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ -+ int nr = sensor_attr->index; \ -+ u32 val = simple_strtoul(buf, NULL, 10); \ -+ \ -+ mutex_lock(&data->update_lock); \ -+ data->in_##reg[nr] = in_to_reg(val, nr); \ -+ w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ -+ data->in_##reg[nr]); \ -+ mutex_unlock(&data->update_lock); \ -+ return count; \ -+} -+ -+store_in_reg(MIN, min) -+store_in_reg(MAX, max) -+ -+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct w83627ehf_data *data = w83627ehf_update_device(dev); -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01); -+} -+ -+static struct sensor_device_attribute sda_in_input[] = { -+ SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), -+ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), -+ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), -+ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), -+ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), -+ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), -+ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), -+ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), -+ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), -+ SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), -+}; -+ -+static struct sensor_device_attribute sda_in_alarm[] = { -+ SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), -+ SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), -+ SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), -+ SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), -+ SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), -+ SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), -+ SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), -+ SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), -+ SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), -+ SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), -+}; -+ -+static struct sensor_device_attribute sda_in_min[] = { -+ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), -+ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), -+ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), -+ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), -+ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), -+ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), -+ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), -+ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), -+ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), -+ SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), -+}; -+ -+static struct sensor_device_attribute sda_in_max[] = { -+ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), -+ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), -+ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), -+ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), -+ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), -+ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), -+ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), -+ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), -+ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), -+ SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), -+}; -+ -+static void device_create_file_in(struct device *dev, int i) -+{ -+ device_create_file(dev, &sda_in_input[i].dev_attr); -+ device_create_file(dev, &sda_in_alarm[i].dev_attr); -+ device_create_file(dev, &sda_in_min[i].dev_attr); -+ device_create_file(dev, &sda_in_max[i].dev_attr); -+} - - #define show_fan_reg(reg) \ - static ssize_t \ --show_##reg(struct device *dev, char *buf, int nr) \ -+show_##reg(struct device *dev, struct device_attribute *attr, \ -+ char *buf) \ - { \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ -+ int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", \ - fan_from_reg(data->reg[nr], \ - div_from_reg(data->fan_div[nr]))); \ -@@ -418,23 +570,28 @@ - show_fan_reg(fan_min); - - static ssize_t --show_fan_div(struct device *dev, char *buf, int nr) -+show_fan_div(struct device *dev, struct device_attribute *attr, -+ char *buf) - { - struct w83627ehf_data *data = w83627ehf_update_device(dev); -- return sprintf(buf, "%u\n", -- div_from_reg(data->fan_div[nr])); -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); - } - - static ssize_t --store_fan_min(struct device *dev, const char *buf, size_t count, int nr) -+store_fan_min(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) - { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; - unsigned int val = simple_strtoul(buf, NULL, 10); - unsigned int reg; - u8 new_div; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - if (!val) { - /* No min limit, alarm disabled */ - data->fan_min[nr] = 255; -@@ -482,63 +639,55 @@ - } - w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], - data->fan_min[nr]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return count; - } - --#define sysfs_fan_offset(offset) \ --static ssize_t \ --show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \ -- char *buf) \ --{ \ -- return show_fan(dev, buf, offset-1); \ --} \ --static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ -- show_reg_fan_##offset, NULL); -+static struct sensor_device_attribute sda_fan_input[] = { -+ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), -+ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), -+ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), -+ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), -+ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), -+}; - --#define sysfs_fan_min_offset(offset) \ --static ssize_t \ --show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ -- char *buf) \ --{ \ -- return show_fan_min(dev, buf, offset-1); \ --} \ --static ssize_t \ --store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ -- const char *buf, size_t count) \ --{ \ -- return store_fan_min(dev, buf, count, offset-1); \ --} \ --static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ -- show_reg_fan##offset##_min, \ -- store_reg_fan##offset##_min); -+static struct sensor_device_attribute sda_fan_alarm[] = { -+ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), -+ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), -+ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 10), -+ SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 11), -+ SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), -+}; - --#define sysfs_fan_div_offset(offset) \ --static ssize_t \ --show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \ -- char *buf) \ --{ \ -- return show_fan_div(dev, buf, offset - 1); \ --} \ --static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ -- show_reg_fan##offset##_div, NULL); -- --sysfs_fan_offset(1); --sysfs_fan_min_offset(1); --sysfs_fan_div_offset(1); --sysfs_fan_offset(2); --sysfs_fan_min_offset(2); --sysfs_fan_div_offset(2); --sysfs_fan_offset(3); --sysfs_fan_min_offset(3); --sysfs_fan_div_offset(3); --sysfs_fan_offset(4); --sysfs_fan_min_offset(4); --sysfs_fan_div_offset(4); --sysfs_fan_offset(5); --sysfs_fan_min_offset(5); --sysfs_fan_div_offset(5); -+static struct sensor_device_attribute sda_fan_min[] = { -+ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 0), -+ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 1), -+ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 2), -+ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 3), -+ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, -+ store_fan_min, 4), -+}; -+ -+static struct sensor_device_attribute sda_fan_div[] = { -+ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), -+ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), -+ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), -+ SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), -+ SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), -+}; -+ -+static void device_create_file_fan(struct device *dev, int i) -+{ -+ device_create_file(dev, &sda_fan_input[i].dev_attr); -+ device_create_file(dev, &sda_fan_alarm[i].dev_attr); -+ device_create_file(dev, &sda_fan_div[i].dev_attr); -+ device_create_file(dev, &sda_fan_min[i].dev_attr); -+} - - #define show_temp1_reg(reg) \ - static ssize_t \ -@@ -561,27 +710,24 @@ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ - u32 val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->temp1_##reg = temp1_to_reg(val); \ - w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ - data->temp1_##reg); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_temp1_reg(OVER, max); - store_temp1_reg(HYST, max_hyst); - --static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL); --static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR, -- show_temp1_max, store_temp1_max); --static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR, -- show_temp1_max_hyst, store_temp1_max_hyst); -- - #define show_temp_reg(reg) \ - static ssize_t \ --show_##reg (struct device *dev, char *buf, int nr) \ -+show_##reg(struct device *dev, struct device_attribute *attr, \ -+ char *buf) \ - { \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ -+ int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", \ - LM75_TEMP_FROM_REG(data->reg[nr])); \ - } -@@ -591,55 +737,45 @@ - - #define store_temp_reg(REG, reg) \ - static ssize_t \ --store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ -+store_##reg(struct device *dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ - { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ -+ int nr = sensor_attr->index; \ - u32 val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->reg[nr] = LM75_TEMP_TO_REG(val); \ - w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ - data->reg[nr]); \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_temp_reg(OVER, temp_max); - store_temp_reg(HYST, temp_max_hyst); - --#define sysfs_temp_offset(offset) \ --static ssize_t \ --show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \ -- char *buf) \ --{ \ -- return show_temp(dev, buf, offset - 2); \ --} \ --static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ -- show_reg_temp##offset, NULL); -- --#define sysfs_temp_reg_offset(reg, offset) \ --static ssize_t \ --show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ -- char *buf) \ --{ \ -- return show_temp_##reg(dev, buf, offset - 2); \ --} \ --static ssize_t \ --store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ -- const char *buf, size_t count) \ --{ \ -- return store_temp_##reg(dev, buf, count, offset - 2); \ --} \ --static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ -- show_reg_temp##offset##_##reg, \ -- store_reg_temp##offset##_##reg); -- --sysfs_temp_offset(2); --sysfs_temp_reg_offset(max, 2); --sysfs_temp_reg_offset(max_hyst, 2); --sysfs_temp_offset(3); --sysfs_temp_reg_offset(max, 3); --sysfs_temp_reg_offset(max_hyst, 3); -+static struct sensor_device_attribute sda_temp[] = { -+ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), -+ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), -+ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), -+ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, -+ store_temp1_max, 0), -+ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, -+ store_temp_max, 0), -+ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, -+ store_temp_max, 1), -+ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, -+ store_temp1_max_hyst, 0), -+ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, -+ store_temp_max_hyst, 0), -+ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, -+ store_temp_max_hyst, 1), -+ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), -+ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), -+ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), -+}; - - /* - * Driver and client management -@@ -673,6 +809,7 @@ - { - struct i2c_client *client; - struct w83627ehf_data *data; -+ struct device *dev; - int i, err = 0; - - if (!request_region(address + REGION_OFFSET, REGION_LENGTH, -@@ -689,14 +826,15 @@ - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - client->adapter = adapter; - client->driver = &w83627ehf_driver; - client->flags = 0; -+ dev = &client->dev; - - strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the i2c layer a new client has arrived */ - if ((err = i2c_attach_client(client))) -@@ -720,42 +858,21 @@ - data->has_fan |= (1 << 4); - - /* Register sysfs hooks */ -- data->class_dev = hwmon_device_register(&client->dev); -+ data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); - goto exit_detach; - } - -- device_create_file(&client->dev, &dev_attr_fan1_input); -- device_create_file(&client->dev, &dev_attr_fan1_min); -- device_create_file(&client->dev, &dev_attr_fan1_div); -- device_create_file(&client->dev, &dev_attr_fan2_input); -- device_create_file(&client->dev, &dev_attr_fan2_min); -- device_create_file(&client->dev, &dev_attr_fan2_div); -- device_create_file(&client->dev, &dev_attr_fan3_input); -- device_create_file(&client->dev, &dev_attr_fan3_min); -- device_create_file(&client->dev, &dev_attr_fan3_div); -- -- if (data->has_fan & (1 << 3)) { -- device_create_file(&client->dev, &dev_attr_fan4_input); -- device_create_file(&client->dev, &dev_attr_fan4_min); -- device_create_file(&client->dev, &dev_attr_fan4_div); -- } -- if (data->has_fan & (1 << 4)) { -- device_create_file(&client->dev, &dev_attr_fan5_input); -- device_create_file(&client->dev, &dev_attr_fan5_min); -- device_create_file(&client->dev, &dev_attr_fan5_div); -- } -- -- device_create_file(&client->dev, &dev_attr_temp1_input); -- device_create_file(&client->dev, &dev_attr_temp1_max); -- device_create_file(&client->dev, &dev_attr_temp1_max_hyst); -- device_create_file(&client->dev, &dev_attr_temp2_input); -- device_create_file(&client->dev, &dev_attr_temp2_max); -- device_create_file(&client->dev, &dev_attr_temp2_max_hyst); -- device_create_file(&client->dev, &dev_attr_temp3_input); -- device_create_file(&client->dev, &dev_attr_temp3_max); -- device_create_file(&client->dev, &dev_attr_temp3_max_hyst); -+ for (i = 0; i < 10; i++) -+ device_create_file_in(dev, i); -+ -+ for (i = 0; i < 5; i++) { -+ if (data->has_fan & (1 << i)) -+ device_create_file_fan(dev, i); -+ } -+ for (i = 0; i < ARRAY_SIZE(sda_temp); i++) -+ device_create_file(dev, &sda_temp[i].dev_attr); - - return 0; - ---- linux-2.6.16.orig/drivers/hwmon/w83627hf.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/w83627hf.c 2006-03-22 17:06:21.000000000 +0100 -@@ -28,6 +28,7 @@ - w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) - w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) - w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) -+ w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) - w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) - - For other winbond chips, and for i2c support in the above chips, -@@ -45,7 +46,9 @@ - #include <linux/i2c-isa.h> - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> -+#include <linux/hwmon-sysfs.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - #include "lm75.h" - -@@ -62,7 +65,7 @@ - static unsigned short address; - - /* Insmod parameters */ --enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; -+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; - - static int reset; - module_param(reset, bool, 0); -@@ -100,6 +103,10 @@ - #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ - #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ - -+#define W83687THF_VID_EN 0x29 /* w83687thf only */ -+#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ -+#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ -+ - static inline void - superio_outb(int reg, int val) - { -@@ -138,6 +145,7 @@ - #define W627THF_DEVID 0x82 - #define W697_DEVID 0x60 - #define W637_DEVID 0x70 -+#define W687THF_DEVID 0x85 - #define WINB_ACT_REG 0x30 - #define WINB_BASE_REG 0x60 - /* Constants specified below */ -@@ -201,11 +209,11 @@ - #define W83627HF_REG_PWM1 0x5A - #define W83627HF_REG_PWM2 0x5B - --#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ --#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ --#define W83627THF_REG_PWM3 0x11 /* 637HF too */ -+#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ -+#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ -+#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ - --#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ -+#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ - - static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; - static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, -@@ -285,10 +293,10 @@ - struct w83627hf_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -318,16 +326,15 @@ - Default = 3435. - Other Betas unimplemented */ - u8 vrm; -- u8 vrm_ovt; /* Register value, 627thf & 637hf only */ -+ u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ - }; - - - static int w83627hf_detect(struct i2c_adapter *adapter); - static int w83627hf_detach_client(struct i2c_client *client); - --static int w83627hf_read_value(struct i2c_client *client, u16 register); --static int w83627hf_write_value(struct i2c_client *client, u16 register, -- u16 value); -+static int w83627hf_read_value(struct i2c_client *client, u16 reg); -+static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); - static struct w83627hf_data *w83627hf_update_device(struct device *dev); - static void w83627hf_init_client(struct i2c_client *client); - -@@ -360,12 +367,12 @@ - \ - val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_in_reg(MIN, min) -@@ -413,7 +420,8 @@ - long in0; - - if ((data->vrm_ovt & 0x01) && -- (w83627thf == data->type || w83637hf == data->type)) -+ (w83627thf == data->type || w83637hf == data->type -+ || w83687thf == data->type)) - - /* use VRM9 calculation */ - in0 = (long)((reg * 488 + 70000 + 50) / 100); -@@ -451,10 +459,11 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if ((data->vrm_ovt & 0x01) && -- (w83627thf == data->type || w83637hf == data->type)) -+ (w83627thf == data->type || w83637hf == data->type -+ || w83687thf == data->type)) - - /* use VRM9 calculation */ - data->in_min[0] = -@@ -465,7 +474,7 @@ - data->in_min[0] = IN_TO_REG(val); - - w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -478,10 +487,11 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if ((data->vrm_ovt & 0x01) && -- (w83627thf == data->type || w83637hf == data->type)) -+ (w83627thf == data->type || w83637hf == data->type -+ || w83687thf == data->type)) - - /* use VRM9 calculation */ - data->in_max[0] = -@@ -492,7 +502,7 @@ - data->in_max[0] = IN_TO_REG(val); - - w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -507,6 +517,10 @@ - device_create_file(&client->dev, &dev_attr_in##offset##_input); \ - device_create_file(&client->dev, &dev_attr_in##offset##_min); \ - device_create_file(&client->dev, &dev_attr_in##offset##_max); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_in##offset##_alarm.dev_attr); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_in##offset##_beep.dev_attr); \ - } while (0) - - #define show_fan_reg(reg) \ -@@ -529,13 +543,13 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->fan_min[nr - 1] = - FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); - w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), - data->fan_min[nr - 1]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -570,6 +584,10 @@ - do { \ - device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ - device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_fan##offset##_alarm.dev_attr); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_fan##offset##_beep.dev_attr); \ - } while (0) - - #define show_temp_reg(reg) \ -@@ -597,7 +615,7 @@ - \ - val = simple_strtoul(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ -@@ -609,7 +627,7 @@ - data->temp_##reg); \ - } \ - \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_temp_reg(OVER, max); -@@ -651,6 +669,10 @@ - device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ - device_create_file(&client->dev, &dev_attr_temp##offset##_max); \ - device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_temp##offset##_alarm.dev_attr); \ -+device_create_file(&client->dev, \ -+ &sensor_dev_attr_temp##offset##_beep.dev_attr); \ - } while (0) - - static ssize_t -@@ -693,76 +715,152 @@ - } - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - #define device_create_file_alarms(client) \ --device_create_file(&client->dev, &dev_attr_alarms) -+do { \ -+device_create_file(&client->dev, &dev_attr_alarms); \ -+device_create_file(&client->dev, &sensor_dev_attr_chassis_alarm.dev_attr); \ -+} while (0) - --#define show_beep_reg(REG, reg) \ --static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ --{ \ -- struct w83627hf_data *data = w83627hf_update_device(dev); \ -- return sprintf(buf,"%ld\n", \ -- (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \ -+static ssize_t -+show_alarm_bit(struct device *dev, struct device_attribute *devattr, char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ struct w83627hf_data *data = w83627hf_update_device(dev); -+ -+ return sprintf(buf, "%u\n", (data->alarms >> attr->index) & 1); - } --show_beep_reg(ENABLE, enable) --show_beep_reg(MASK, mask) -+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm_bit, NULL, 0); -+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm_bit, NULL, 1); -+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm_bit, NULL, 2); -+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm_bit, NULL, 3); -+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm_bit, NULL, 8); -+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm_bit, NULL, 9); -+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm_bit, NULL, 10); -+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm_bit, NULL, 16); -+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm_bit, NULL, 17); -+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm_bit, NULL, 6); -+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm_bit, NULL, 7); -+static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm_bit, NULL, 11); -+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm_bit, NULL, 4); -+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm_bit, NULL, 5); -+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm_bit, NULL, 13); -+static SENSOR_DEVICE_ATTR(chassis_alarm, S_IRUGO, show_alarm_bit, NULL, 12); - --#define BEEP_ENABLE 0 /* Store beep_enable */ --#define BEEP_MASK 1 /* Store beep_mask */ -+static ssize_t show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ struct w83627hf_data *data = w83627hf_update_device(dev); -+ return sprintf(buf, "%ld\n", -+ (long)BEEP_MASK_FROM_REG(data->beep_mask)); -+} - - static ssize_t --store_beep_reg(struct device *dev, const char *buf, size_t count, -- int update_mask) -+store_beep_mask(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) - { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); -- u32 val, val2; -- -- val = simple_strtoul(buf, NULL, 10); -+ u32 val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -- -- if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ -- data->beep_mask = BEEP_MASK_TO_REG(val); -- w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, -- data->beep_mask & 0xff); -- w83627hf_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 = -- w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; -- data->beep_enable = BEEP_ENABLE_TO_REG(val); -- } -+ mutex_lock(&data->update_lock); - -+ data->beep_mask = BEEP_MASK_TO_REG(val); -+ w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, -+ data->beep_mask & 0xff); -+ w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, -+ ((data->beep_mask) >> 16) & 0xff); - w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, -- val2 | data->beep_enable << 7); -+ ((data->beep_mask >> 8) & 0x7f) -+ | data->beep_enable << 7); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } -- --#define sysfs_beep(REG, reg) \ --static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ --{ \ -- return show_beep_##reg(dev, attr, buf); \ --} \ --static ssize_t \ --store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, 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); -+static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, \ -+ show_beep_mask, store_beep_mask); - - #define device_create_file_beep(client) \ - do { \ --device_create_file(&client->dev, &dev_attr_beep_enable); \ -+device_create_file(&client->dev, &sensor_dev_attr_beep_enable.dev_attr); \ - device_create_file(&client->dev, &dev_attr_beep_mask); \ -+device_create_file(&client->dev, &sensor_dev_attr_chassis_beep.dev_attr); \ - } while (0) - - static ssize_t -+show_beep_bit(struct device *dev, struct device_attribute *devattr, char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ struct w83627hf_data *data = w83627hf_update_device(dev); -+ -+ return sprintf(buf, "%u\n", (data->beep_mask >> attr->index) & 1); -+} -+ -+static ssize_t -+store_beep_bit(struct device *dev, struct device_attribute *devattr, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -+ struct w83627hf_data *data = i2c_get_clientdata(client); -+ u16 beepreg[3] = { W83781D_REG_BEEP_INTS1, W83781D_REG_BEEP_INTS2, -+ W83781D_REG_BEEP_INTS3 }; -+ u32 val; -+ u8 reg; -+ -+ val = simple_strtoul(buf, NULL, 10); -+ if (val != 0 && val != 1) -+ return -EINVAL; -+ -+ mutex_lock(&data->update_lock); -+ -+ reg = w83627hf_read_value(client, beepreg[attr->index >> 3]); -+ if (val) { -+ reg |= 1 << (attr->index & 0x07); -+ data->beep_mask |= 1 << attr->index; -+ } else { -+ reg &= ~(1 << (attr->index & 0x07)); -+ data->beep_mask &= ~(1 << attr->index); -+ } -+ w83627hf_write_value(client, beepreg[attr->index >> 3], reg); -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 0); -+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 1); -+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 2); -+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 3); -+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 8); -+static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 9); -+static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 10); -+static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 16); -+static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 17); -+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 6); -+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 7); -+static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 11); -+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 4); -+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 5); -+static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 13); -+static SENSOR_DEVICE_ATTR(chassis_beep, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 12); -+static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, show_beep_bit, -+ store_beep_bit, 15); -+ -+static ssize_t - show_fan_div_reg(struct device *dev, char *buf, int nr) - { - struct w83627hf_data *data = w83627hf_update_device(dev); -@@ -783,7 +881,7 @@ - u8 reg; - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], -@@ -805,7 +903,7 @@ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -848,7 +946,7 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (data->type == w83627thf) { - /* bits 0-3 are reserved in 627THF */ -@@ -865,7 +963,7 @@ - data->pwm[nr - 1]); - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -907,7 +1005,7 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - switch (val) { - case 1: /* PII/Celeron diode */ -@@ -941,7 +1039,7 @@ - break; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -980,7 +1078,8 @@ - if(val != W627_DEVID && - val != W627THF_DEVID && - val != W697_DEVID && -- val != W637_DEVID) { -+ val != W637_DEVID && -+ val != W687THF_DEVID) { - superio_exit(); - return -ENODEV; - } -@@ -1034,6 +1133,8 @@ - kind = w83627thf; - else if(val == W637_DEVID) - kind = w83637hf; -+ else if (val == W687THF_DEVID) -+ kind = w83687thf; - else { - dev_info(&adapter->dev, - "Unsupported chip (dev_id=0x%02X).\n", val); -@@ -1057,7 +1158,7 @@ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - new_client->adapter = adapter; - new_client->driver = &w83627hf_driver; - new_client->flags = 0; -@@ -1071,13 +1172,15 @@ - client_name = "w83697hf"; - } else if (kind == w83637hf) { - client_name = "w83637hf"; -+ } else if (kind == w83687thf) { -+ client_name = "w83687thf"; - } - - /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -1106,7 +1209,7 @@ - device_create_file_in(new_client, 2); - device_create_file_in(new_client, 3); - device_create_file_in(new_client, 4); -- if (kind != w83627thf && kind != w83637hf) { -+ if (kind == w83627hf || kind == w83697hf) { - device_create_file_in(new_client, 5); - device_create_file_in(new_client, 6); - } -@@ -1139,7 +1242,7 @@ - - device_create_file_pwm(new_client, 1); - device_create_file_pwm(new_client, 2); -- if (kind == w83627thf || kind == w83637hf) -+ if (kind == w83627thf || kind == w83637hf || kind == w83687thf) - device_create_file_pwm(new_client, 3); - - device_create_file_sensor(new_client, 1); -@@ -1187,7 +1290,7 @@ - struct w83627hf_data *data = i2c_get_clientdata(client); - int res, word_sized; - -- down(&data->lock); -+ mutex_lock(&data->lock); - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x50) -@@ -1213,7 +1316,7 @@ - client->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); - } -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } - -@@ -1247,12 +1350,39 @@ - return res; - } - -+static int w83687thf_read_vid(struct i2c_client *client) -+{ -+ int res = 0xff; -+ -+ superio_enter(); -+ superio_select(W83627HF_LD_HWM); -+ -+ /* Make sure these GPIO pins are enabled */ -+ if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { -+ dev_dbg(&client->dev, "VID disabled, no VID function\n"); -+ goto exit; -+ } -+ -+ /* Make sure the pins are configured for input */ -+ if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { -+ dev_dbg(&client->dev, "VID configured as output, " -+ "no VID function\n"); -+ goto exit; -+ } -+ -+ res = superio_inb(W83687THF_VID_DATA) & 0x3f; -+ -+exit: -+ superio_exit(); -+ return res; -+} -+ - static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) - { - struct w83627hf_data *data = i2c_get_clientdata(client); - int word_sized; - -- down(&data->lock); -+ mutex_lock(&data->lock); - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x53) -@@ -1277,7 +1407,7 @@ - client->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); - } -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } - -@@ -1324,10 +1454,13 @@ - data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); - } else if (w83627thf == data->type) { - data->vid = w83627thf_read_gpio5(client); -+ } else if (w83687thf == data->type) { -+ data->vid = w83687thf_read_vid(client); - } - - /* Read VRM & OVT Config only once */ -- if (w83627thf == data->type || w83637hf == data->type) { -+ if (w83627thf == data->type || w83637hf == data->type -+ || w83687thf == data->type) { - data->vrm_ovt = - w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); - } -@@ -1387,14 +1520,14 @@ - struct w83627hf_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - for (i = 0; i <= 8; i++) { - /* skip missing sensors */ - if (((data->type == w83697hf) && (i == 1)) || -- ((data->type == w83627thf || data->type == w83637hf) -+ ((data->type != w83627hf && data->type != w83697hf) - && (i == 5 || i == 6))) - continue; - data->in[i] = -@@ -1470,7 +1603,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/w83781d.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/w83781d.c 2006-03-22 17:06:16.000000000 +0100 -@@ -42,6 +42,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-vid.h> - #include <linux/err.h> -+#include <linux/mutex.h> - #include <asm/io.h> - #include "lm75.h" - -@@ -56,6 +57,10 @@ - I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -+static int reset; -+module_param(reset, bool, 0); -+MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); -+ - static int init = 1; - module_param(init, bool, 0); - MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); -@@ -226,10 +231,10 @@ - struct w83781d_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore lock; -+ struct mutex lock; - enum chips type; - -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - -@@ -262,14 +267,12 @@ - u8 vrm; - }; - --static int w83781d_attach_adapter(struct i2c_adapter *adapter); - static int w83781d_isa_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 int w83781d_read_value(struct i2c_client *client, u16 reg); -+static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); - static struct w83781d_data *w83781d_update_device(struct device *dev); - static void w83781d_init_client(struct i2c_client *client); - -@@ -278,7 +281,9 @@ - .name = "w83781d", - }, - .id = I2C_DRIVERID_W83781D, -- .attach_adapter = w83781d_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = w83781d_detect, - .detach_client = w83781d_detach_client, - }; - -@@ -311,11 +316,11 @@ - \ - val = simple_strtoul(buf, NULL, 10) / 10; \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ - \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_in_reg(MIN, min); -@@ -381,13 +386,13 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - 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]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -446,7 +451,7 @@ - \ - val = simple_strtol(buf, NULL, 10); \ - \ -- down(&data->update_lock); \ -+ mutex_lock(&data->update_lock); \ - \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ -@@ -458,7 +463,7 @@ - data->temp_##reg); \ - } \ - \ -- up(&data->update_lock); \ -+ mutex_unlock(&data->update_lock); \ - return count; \ - } - store_temp_reg(OVER, max); -@@ -571,7 +576,7 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ - data->beep_mask = BEEP_MASK_TO_REG(val, data->type); -@@ -592,7 +597,7 @@ - w83781d_write_value(client, W83781D_REG_BEEP_INTS2, - val2 | data->beep_enable << 7); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -637,7 +642,7 @@ - u8 reg; - unsigned long val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], -@@ -662,7 +667,7 @@ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -709,10 +714,10 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - data->pwm[nr - 1] = PWM_TO_REG(val); - w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -725,7 +730,7 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - switch (val) { - case 0: -@@ -742,11 +747,11 @@ - break; - - default: -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return -EINVAL; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -808,7 +813,7 @@ - - val = simple_strtoul(buf, NULL, 10); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - switch (val) { - case 1: /* PII/Celeron diode */ -@@ -841,7 +846,7 @@ - break; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - return count; - } - -@@ -865,18 +870,6 @@ - device_create_file(&client->dev, &dev_attr_temp##offset##_type); \ - } while (0) - --/* 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) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, w83781d_detect); --} -- - static int - w83781d_isa_attach_adapter(struct i2c_adapter *adapter) - { -@@ -1073,7 +1066,7 @@ - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; -- init_MUTEX(&data->lock); -+ mutex_init(&data->lock); - new_client->adapter = adapter; - new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; - new_client->flags = 0; -@@ -1178,7 +1171,7 @@ - data->type = kind; - - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) -@@ -1325,7 +1318,7 @@ - int res, word_sized, bank; - struct i2c_client *cl; - -- down(&data->lock); -+ mutex_lock(&data->lock); - if (i2c_is_isa_client(client)) { - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) -@@ -1383,7 +1376,7 @@ - if (bank > 2) - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); - } -- up(&data->lock); -+ mutex_unlock(&data->lock); - return res; - } - -@@ -1394,7 +1387,7 @@ - int word_sized, bank; - struct i2c_client *cl; - -- down(&data->lock); -+ mutex_lock(&data->lock); - if (i2c_is_isa_client(client)) { - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) -@@ -1447,7 +1440,7 @@ - if (bank > 2) - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); - } -- up(&data->lock); -+ mutex_unlock(&data->lock); - return 0; - } - -@@ -1459,8 +1452,17 @@ - int type = data->type; - u8 tmp; - -- if (init && type != as99127f) { /* this resets registers we don't have -+ if (reset && type != as99127f) { /* this resets registers we don't have - documentation for on the as99127f */ -+ /* Resetting the chip has been the default for a long time, -+ but it causes the BIOS initializations (fan clock dividers, -+ thermal sensor types...) to be lost, so it is now optional. -+ It might even go away if nobody reports it as being useful, -+ as I see very little reason why this would be needed at -+ all. */ -+ dev_info(&client->dev, "If reset=1 solved a problem you were " -+ "having, please report!\n"); -+ - /* save these registers */ - i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); - p = w83781d_read_value(client, W83781D_REG_PWMCLK12); -@@ -1477,6 +1479,13 @@ - w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); - } - -+ /* Disable power-on abnormal beep, as advised by the datasheet. -+ Already done if reset=1. */ -+ if (init && !reset && type != as99127f) { -+ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); -+ w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); -+ } -+ - data->vrm = vid_which_vrm(); - - if ((type != w83781d) && (type != as99127f)) { -@@ -1533,7 +1542,7 @@ - struct w83781d_data *data = i2c_get_clientdata(client); - int i; - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { -@@ -1641,7 +1650,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/drivers/hwmon/w83l785ts.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/w83l785ts.c 2006-03-22 17:06:16.000000000 +0100 -@@ -39,6 +39,7 @@ - #include <linux/hwmon.h> - #include <linux/hwmon-sysfs.h> - #include <linux/err.h> -+#include <linux/mutex.h> - - /* How many retries on register read error */ - #define MAX_RETRIES 5 -@@ -80,7 +81,6 @@ - * Functions declaration - */ - --static int w83l785ts_attach_adapter(struct i2c_adapter *adapter); - static int w83l785ts_detect(struct i2c_adapter *adapter, int address, - int kind); - static int w83l785ts_detach_client(struct i2c_client *client); -@@ -96,7 +96,9 @@ - .name = "w83l785ts", - }, - .id = I2C_DRIVERID_W83L785TS, -- .attach_adapter = w83l785ts_attach_adapter, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = w83l785ts_detect, - .detach_client = w83l785ts_detach_client, - }; - -@@ -107,7 +109,7 @@ - struct w83l785ts_data { - struct i2c_client client; - struct class_device *class_dev; -- struct semaphore update_lock; -+ struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - -@@ -135,13 +137,6 @@ - * Real code - */ - --static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) --{ -- if (!(adapter->class & I2C_CLASS_HWMON)) -- return 0; -- return i2c_probe(adapter, &addr_data, w83l785ts_detect); --} -- - /* - * The following function does more than just detection. If detection - * succeeds, it also registers the new chip. -@@ -221,7 +216,7 @@ - /* We can fill in the remaining client fields. */ - strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); - data->valid = 0; -- init_MUTEX(&data->update_lock); -+ mutex_init(&data->update_lock); - - /* Default values in case the first read fails (unlikely). */ - data->temp[1] = data->temp[0] = 0; -@@ -299,7 +294,7 @@ - struct i2c_client *client = to_i2c_client(dev); - struct w83l785ts_data *data = i2c_get_clientdata(client); - -- down(&data->update_lock); -+ mutex_lock(&data->update_lock); - - if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { - dev_dbg(&client->dev, "Updating w83l785ts data.\n"); -@@ -312,7 +307,7 @@ - data->valid = 1; - } - -- up(&data->update_lock); -+ mutex_unlock(&data->update_lock); - - return data; - } ---- linux-2.6.16.orig/Documentation/hwmon/w83627hf 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/Documentation/hwmon/w83627hf 2006-03-22 17:06:15.000000000 +0100 -@@ -18,6 +18,10 @@ - Prefix: 'w83637hf' - Addresses scanned: ISA address retrieved from Super I/O registers - Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf -+ * Winbond W83687THF -+ Prefix: 'w83687thf' -+ Addresses scanned: ISA address retrieved from Super I/O registers -+ Datasheet: Provided by Winbond on request - - Authors: - Frodo Looijaard <frodol@dds.nl>, ---- linux-2.6.16.orig/drivers/hwmon/Kconfig 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/Kconfig 2006-03-22 17:06:16.000000000 +0100 -@@ -236,11 +236,11 @@ - will be called lm80. - - config SENSORS_LM83 -- tristate "National Semiconductor LM83" -+ tristate "National Semiconductor LM83 and compatibles" - depends on HWMON && I2C - help - If you say yes here you get support for National Semiconductor -- LM83 sensor chips. -+ LM82 and LM83 sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm83. -@@ -333,11 +333,32 @@ - help - If you say yes here you get support for the integrated fan - monitoring and control capabilities of the SMSC LPC47B27x, -- LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips. -+ LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and -+ LPC47M997 chips. -+ -+ The temperature and voltage sensor features of the LPC47M192 -+ and LPC47M997 are supported by another driver, select also -+ "SMSC LPC47M192 and compatibles" below for those. - - This driver can also be built as a module. If so, the module - will be called smsc47m1. - -+config SENSORS_SMSC47M192 -+ tristate "SMSC LPC47M192 and compatibles" -+ depends on HWMON && I2C && EXPERIMENTAL -+ select HWMON_VID -+ help -+ If you say yes here you get support for the temperature and -+ voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. -+ -+ The fan monitoring and control capabilities of these chips -+ are supported by another driver, select -+ "SMSC LPC47M10x and compatibles" above. You need both drivers -+ if you want fan control and voltage/temperature sensor support. -+ -+ This driver can also be built as a module. If so, the module -+ will be called smsc47m192. -+ - config SENSORS_SMSC47B397 - tristate "SMSC LPC47B397-NC" - depends on HWMON && I2C && EXPERIMENTAL -@@ -406,13 +427,14 @@ - will be called w83l785ts. - - config SENSORS_W83627HF -- tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" -- depends on HWMON && I2C && EXPERIMENTAL -+ tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" -+ depends on HWMON && I2C - select I2C_ISA - select HWMON_VID - help - If you say yes here you get support for the Winbond W836X7 series -- of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF -+ of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and -+ W83697HF. - - This driver can also be built as a module. If so, the module - will be called w83627hf. ---- linux-2.6.16.orig/drivers/hwmon/hwmon-vid.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/hwmon-vid.c 2006-03-22 17:06:15.000000000 +0100 -@@ -54,6 +54,10 @@ - (IMVP-II). You can find more information in the datasheet of Max1718 - http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 - -+ The 13 specification corresponds to the Intel Pentium M series. There -+ doesn't seem to be any named specification for these. The conversion -+ tables are detailed directly in the various Pentium M datasheets: -+ http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm - */ - - /* vrm is the VRM/VRD document version multiplied by 10. -@@ -100,6 +104,8 @@ - case 17: /* Intel IMVP-II */ - return(val & 0x10 ? 975 - (val & 0xF) * 25 : - 1750 - val * 50); -+ case 13: -+ return(1708 - (val & 0x3f) * 16); - default: /* report 0 for unknown */ - printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); - return 0; -@@ -129,8 +135,9 @@ - static struct vrm_model vrm_models[] = { - {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ - {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ -- {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */ -+ {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ - {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ -+ {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ - {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ - {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ - {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ ---- linux-2.6.16.orig/Documentation/hwmon/w83781d 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/Documentation/hwmon/w83781d 2006-03-22 17:06:15.000000000 +0100 -@@ -36,6 +36,11 @@ - Use 'init=0' to bypass initializing the chip. - Try this if your computer crashes when you load the module. - -+* reset int -+ (default 0) -+ The driver used to reset the chip on load, but does no more. Use -+ 'reset=1' to restore the old behavior. Report if you need to do this. -+ - force_subclients=bus,caddr,saddr,saddr - This is used to force the i2c addresses for subclients of - a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' -@@ -123,6 +128,25 @@ - your computer speaker. It is possible to enable all beeping globally, - or only the beeping for some alarms. - -+Individual alarm and beep bits: -+ -+0x000001: in0 -+0x000002: in1 -+0x000004: in2 -+0x000008: in3 -+0x000010: temp1 -+0x000020: temp2 (+temp3 on W83781D) -+0x000040: fan1 -+0x000080: fan2 -+0x000100: in4 -+0x000200: in5 -+0x000400: in6 -+0x000800: fan3 -+0x001000: chassis -+0x002000: temp3 (W83782D and W83627HF only) -+0x010000: in7 (W83782D and W83627HF only) -+0x020000: in8 (W83782D and W83627HF only) -+ - If an alarm triggers, it will remain triggered until the hardware register - is read at least once. This means that the cause for the alarm may - already have disappeared! Note that in the current implementation, all ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-frodo.c 2006-03-22 17:06:09.000000000 +0100 -+++ /dev/null 1970-01-01 00:00:00.000000000 +0000 -@@ -1,85 +0,0 @@ -- --/* -- * linux/drivers/i2c/i2c-frodo.c -- * -- * Author: Abraham van der Merwe <abraham@2d3d.co.za> -- * -- * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 -- * Development board (Frodo). -- * -- * This source code is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License -- * version 2 as published by the Free Software Foundation. -- */ -- --#include <linux/module.h> --#include <linux/kernel.h> --#include <linux/init.h> --#include <linux/delay.h> --#include <linux/i2c.h> --#include <linux/i2c-algo-bit.h> --#include <asm/hardware.h> -- -- --static void frodo_setsda (void *data,int state) --{ -- if (state) -- FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; -- else -- FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; --} -- --static void frodo_setscl (void *data,int state) --{ -- if (state) -- FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; -- else -- FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; --} -- --static int frodo_getsda (void *data) --{ -- return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); --} -- --static int frodo_getscl (void *data) --{ -- return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); --} -- --static struct i2c_algo_bit_data bit_frodo_data = { -- .setsda = frodo_setsda, -- .setscl = frodo_setscl, -- .getsda = frodo_getsda, -- .getscl = frodo_getscl, -- .udelay = 80, -- .mdelay = 80, -- .timeout = HZ --}; -- --static struct i2c_adapter frodo_ops = { -- .owner = THIS_MODULE, -- .id = I2C_HW_B_FRODO, -- .algo_data = &bit_frodo_data, -- .dev = { -- .name = "Frodo adapter driver", -- }, --}; -- --static int __init i2c_frodo_init (void) --{ -- return i2c_bit_add_bus(&frodo_ops); --} -- --static void __exit i2c_frodo_exit (void) --{ -- i2c_bit_del_bus(&frodo_ops); --} -- --MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); --MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); --MODULE_LICENSE ("GPL"); -- --module_init (i2c_frodo_init); --module_exit (i2c_frodo_exit); -- ---- linux-2.6.16.orig/include/linux/i2c-id.h 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/include/linux/i2c-id.h 2006-03-22 17:06:15.000000000 +0100 -@@ -172,7 +172,6 @@ - #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ - #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ - #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ --#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */ - #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ - #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ - #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ite.c 2006-03-22 17:06:09.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ite.c 2006-03-22 17:06:15.000000000 +0100 -@@ -200,9 +200,7 @@ - .owner = THIS_MODULE, - .id = I2C_HW_I_IIC, - .algo_data = &iic_ite_data, -- .dev = { -- .name = "ITE IIC adapter", -- }, -+ .name = "ITE IIC adapter", - }; - - /* Called when the module is loaded. This function starts the ---- linux-2.6.16.orig/drivers/i2c/chips/isp1301_omap.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/chips/isp1301_omap.c 2006-03-22 17:06:15.000000000 +0100 -@@ -1635,8 +1635,6 @@ - .driver = { - .name = "isp1301_omap", - }, -- .id = 1301, /* FIXME "official", i2c-ids.h */ -- .class = I2C_CLASS_HWMON, - .attach_adapter = isp1301_scan_bus, - .detach_client = isp1301_detach_client, - }; ---- linux-2.6.16.orig/Documentation/i2c/busses/i2c-piix4 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/Documentation/i2c/busses/i2c-piix4 2006-03-22 17:06:16.000000000 +0100 -@@ -4,8 +4,10 @@ - * Intel 82371AB PIIX4 and PIIX4E - * Intel 82443MX (440MX) - Datasheet: Publicly available at the Intel website -- * ServerWorks OSB4, CSB5 and CSB6 southbridges -+ * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges - Datasheet: Only available via NDA from ServerWorks -+ * ATI IXP southbridges IXP200, IXP300, IXP400 -+ Datasheet: Not publicly available - * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge - Datasheet: Publicly available at the SMSC website http://www.smsc.com - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-piix4.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-piix4.c 2006-03-22 17:06:16.000000000 +0100 -@@ -22,7 +22,7 @@ - /* - Supports: - Intel PIIX4, 440MX -- Serverworks OSB4, CSB5, CSB6 -+ Serverworks OSB4, CSB5, CSB6, HT-1000 - SMSC Victory66 - - Note: we assume there can only be one device, with one SMBus interface. -@@ -406,19 +406,27 @@ - - static struct i2c_adapter piix4_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - - static struct pci_device_id piix4_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), - .driver_data = 3 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS), -+ .driver_data = 0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS), -+ .driver_data = 0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS), -+ .driver_data = 0 }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), - .driver_data = 0 }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), - .driver_data = 0 }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), - .driver_data = 0 }, -+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), -+ .driver_data = 0 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), - .driver_data = 3 }, - { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), ---- linux-2.6.16.orig/include/linux/pci_ids.h 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/include/linux/pci_ids.h 2006-03-22 17:06:16.000000000 +0100 -@@ -351,8 +351,11 @@ - #define PCI_DEVICE_ID_ATI_RS480 0x5950 - /* ATI IXP Chipset */ - #define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 -+#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 -+#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 - #define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 - #define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e -+#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 - #define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 - #define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 - -@@ -1369,6 +1372,7 @@ - #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 - #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 - #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 -+#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 - #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 - #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 - #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ixp4xx.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ixp4xx.c 2006-03-22 17:06:16.000000000 +0100 -@@ -125,7 +125,9 @@ - drv_data->algo_data.mdelay = 10; - drv_data->algo_data.timeout = 100; - -+ drv_data->adapter.owner = THIS_MODULE; - drv_data->adapter.id = I2C_HW_B_IXP4XX; -+ drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; - strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, - I2C_NAME_SIZE); - drv_data->adapter.algo_data = &drv_data->algo_data; ---- linux-2.6.16.orig/drivers/media/video/adv7170.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/adv7170.c 2006-03-22 17:06:15.000000000 +0100 -@@ -53,7 +53,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(x) (x)->name - -@@ -125,24 +124,21 @@ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct adv7170 *encoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -+ block_data[block_len++] = - encoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { ---- linux-2.6.16.orig/drivers/media/video/adv7175.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/adv7175.c 2006-03-22 17:06:16.000000000 +0100 -@@ -49,7 +49,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -68,8 +67,6 @@ - /* ----------------------------------------------------------------------- */ - - struct adv7175 { -- unsigned char reg[128]; -- - int norm; - int input; - int enable; -@@ -95,9 +92,6 @@ - u8 reg, - u8 value) - { -- struct adv7175 *encoder = i2c_get_clientdata(client); -- -- encoder->reg[reg] = value; - return i2c_smbus_write_byte_data(client, reg, value); - } - -@@ -120,25 +114,21 @@ - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ -- struct adv7175 *encoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -- encoder->reg[reg++] = data[1]; -+ block_data[block_len++] = data[1]; -+ reg++; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { -@@ -171,24 +161,6 @@ - adv7175_write(client, 0x05, 0x25); - } - --#ifdef ENCODER_DUMP --static void --dump (struct i2c_client *client) --{ -- struct adv7175 *encoder = i2c_get_clientdata(client); -- int i, j; -- -- printk(KERN_INFO "%s: registry dump\n", I2C_NAME(client)); -- for (i = 0; i < 182 / 8; i++) { -- printk("%s: 0x%02x -", I2C_NAME(client), i * 8); -- for (j = 0; j < 8; j++) { -- printk(" 0x%02x", encoder->reg[i * 8 + j]); -- } -- printk("\n"); -- } --} --#endif -- - /* ----------------------------------------------------------------------- */ - // Output filter: S-Video Composite - -@@ -407,14 +379,6 @@ - } - break; - --#ifdef ENCODER_DUMP -- case ENCODER_DUMP: -- { -- dump(client); -- } -- break; --#endif -- - default: - return -EINVAL; - } -@@ -424,24 +388,6 @@ - - /* ----------------------------------------------------------------------- */ - --/* -- * Generic i2c probe -- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' -- */ --static unsigned short normal_i2c[] = -- { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, -- I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, -- I2C_CLIENT_END --}; -- --static unsigned short ignore = I2C_CLIENT_END; -- --static struct i2c_client_address_data addr_data = { -- .normal_i2c = normal_i2c, -- .probe = &ignore, -- .ignore = &ignore, --}; -- - static struct i2c_driver i2c_driver_adv7175; - - static int -@@ -516,16 +462,6 @@ - } - - static int --adv7175_attach_adapter (struct i2c_adapter *adapter) --{ -- dprintk(1, -- KERN_INFO -- "adv7175.c: starting probe for adapter %s (0x%x)\n", -- I2C_NAME(adapter), adapter->id); -- return i2c_probe(adapter, &addr_data, &adv7175_detect_client); --} -- --static int - adv7175_detach_client (struct i2c_client *client) - { - struct adv7175 *encoder = i2c_get_clientdata(client); -@@ -551,7 +487,7 @@ - - .id = I2C_DRIVERID_ADV7175, - -- .attach_adapter = adv7175_attach_adapter, -+ .detect_client = adv7175_detect_client, - .detach_client = adv7175_detach_client, - .command = adv7175_command, - }; ---- linux-2.6.16.orig/drivers/media/video/bt819.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/bt819.c 2006-03-22 17:06:15.000000000 +0100 -@@ -53,7 +53,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -141,24 +140,21 @@ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct bt819 *decoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -+ block_data[block_len++] = - decoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { ---- linux-2.6.16.orig/drivers/media/video/bt856.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/bt856.c 2006-03-22 17:06:15.000000000 +0100 -@@ -53,7 +53,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -71,17 +70,14 @@ - - /* ----------------------------------------------------------------------- */ - --#define REG_OFFSET 0xCE -+#define REG_OFFSET 0xDA -+#define BT856_NR_REG 6 - - struct bt856 { -- unsigned char reg[32]; -+ unsigned char reg[BT856_NR_REG]; - - int norm; - int enable; -- int bright; -- int contrast; -- int hue; -- int sat; - }; - - #define I2C_BT856 0x88 -@@ -120,8 +116,8 @@ - struct bt856 *encoder = i2c_get_clientdata(client); - - printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); -- for (i = 0xd6; i <= 0xde; i += 2) -- printk(" %02x", encoder->reg[i - REG_OFFSET]); -+ for (i = 0; i < BT856_NR_REG; i += 2) -+ printk(" %02x", encoder->reg[i]); - printk("\n"); - } - ---- linux-2.6.16.orig/drivers/media/video/saa7110.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/saa7110.c 2006-03-22 17:06:16.000000000 +0100 -@@ -39,7 +39,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -59,8 +58,6 @@ - #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ - #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ - --#define I2C_SAA7110 0x9C /* or 0x9E */ -- - #define SAA7110_NR_REG 0x35 - - struct saa7110 { -@@ -108,13 +105,8 @@ - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - struct saa7110 *decoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - -- msg.len = len; -- msg.buf = (char *) data; -- msg.addr = client->addr; -- msg.flags = 0; -- ret = i2c_transfer(client->adapter, &msg, 1); -+ ret = i2c_master_send(client, data, len); - - /* Cache the written data */ - memcpy(decoder->reg + reg, data + 1, len - 1); -@@ -432,15 +424,13 @@ - break; - - case DECODER_DUMP: -- for (v = 0; v < 0x34; v += 16) { -+ for (v = 0; v < SAA7110_NR_REG; v += 16) { - int j; -- dprintk(1, KERN_INFO "%s: %03x\n", I2C_NAME(client), -+ dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client), - v); -- for (j = 0; j < 16; j++) { -- dprintk(1, KERN_INFO " %02x", -- decoder->reg[v + j]); -- } -- dprintk(1, KERN_INFO "\n"); -+ for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) -+ dprintk(1, " %02x", decoder->reg[v + j]); -+ dprintk(1, "\n"); - } - break; - -@@ -454,24 +444,6 @@ - - /* ----------------------------------------------------------------------- */ - --/* -- * Generic i2c probe -- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' -- */ --static unsigned short normal_i2c[] = { -- I2C_SAA7110 >> 1, -- (I2C_SAA7110 >> 1) + 1, -- I2C_CLIENT_END --}; -- --static unsigned short ignore = I2C_CLIENT_END; -- --static struct i2c_client_address_data addr_data = { -- .normal_i2c = normal_i2c, -- .probe = &ignore, -- .ignore = &ignore, --}; -- - static struct i2c_driver i2c_driver_saa7110; - - static int -@@ -555,16 +527,6 @@ - } - - static int --saa7110_attach_adapter (struct i2c_adapter *adapter) --{ -- dprintk(1, -- KERN_INFO -- "saa7110.c: starting probe for adapter %s (0x%x)\n", -- I2C_NAME(adapter), adapter->id); -- return i2c_probe(adapter, &addr_data, &saa7110_detect_client); --} -- --static int - saa7110_detach_client (struct i2c_client *client) - { - struct saa7110 *decoder = i2c_get_clientdata(client); -@@ -590,7 +552,7 @@ - - .id = I2C_DRIVERID_SAA7110, - -- .attach_adapter = saa7110_attach_adapter, -+ .detect_client = saa7110_detect_client, - .detach_client = saa7110_detach_client, - .command = saa7110_command, - }; ---- linux-2.6.16.orig/drivers/media/video/saa7111.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/saa7111.c 2006-03-22 17:06:15.000000000 +0100 -@@ -52,7 +52,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -70,8 +69,10 @@ - - /* ----------------------------------------------------------------------- */ - -+#define SAA7111_NR_REG 0x18 -+ - struct saa7111 { -- unsigned char reg[32]; -+ unsigned char reg[SAA7111_NR_REG]; - - int norm; - int input; -@@ -110,24 +111,21 @@ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct saa7111 *decoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -+ block_data[block_len++] = - decoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { -@@ -227,11 +225,11 @@ - { - int i; - -- for (i = 0; i < 32; i += 16) { -+ for (i = 0; i < SAA7111_NR_REG; i += 16) { - int j; - - printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); -- for (j = 0; j < 16; ++j) { -+ for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { - printk(" %02x", - saa7111_read(client, i + j)); - } ---- linux-2.6.16.orig/drivers/media/video/saa7114.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/saa7114.c 2006-03-22 17:06:15.000000000 +0100 -@@ -55,7 +55,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(x) (x)->name - -@@ -139,9 +138,6 @@ - u8 reg, - u8 value) - { -- /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ -- -- /*decoder->reg[reg] = value;*/ - return i2c_smbus_write_byte_data(client, reg, value); - } - -@@ -157,25 +153,21 @@ - * the adapter understands raw I2C */ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ -- /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -- /*decoder->reg[reg++] =*/ data[1]; -+ block_data[block_len++] = data[1]; -+ reg++; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { ---- linux-2.6.16.orig/drivers/media/video/saa711x.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/saa711x.c 2006-03-22 17:06:15.000000000 +0100 -@@ -45,7 +45,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - ---- linux-2.6.16.orig/drivers/media/video/saa7185.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/saa7185.c 2006-03-22 17:06:15.000000000 +0100 -@@ -49,7 +49,6 @@ - MODULE_LICENSE("GPL"); - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(s) (s)->name - -@@ -113,24 +112,21 @@ - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - /* do raw I2C, not smbus compatible */ - struct saa7185 *encoder = i2c_get_clientdata(client); -- struct i2c_msg msg; - u8 block_data[32]; -+ int block_len; - -- msg.addr = client->addr; -- msg.flags = 0; - while (len >= 2) { -- msg.buf = (char *) block_data; -- msg.len = 0; -- block_data[msg.len++] = reg = data[0]; -+ block_len = 0; -+ block_data[block_len++] = reg = data[0]; - do { -- block_data[msg.len++] = -+ block_data[block_len++] = - encoder->reg[reg++] = data[1]; - len -= 2; - data += 2; - } while (len >= 2 && data[0] == reg && -- msg.len < 32); -- if ((ret = i2c_transfer(client->adapter, -- &msg, 1)) < 0) -+ block_len < 32); -+ if ((ret = i2c_master_send(client, block_data, -+ block_len)) < 0) - break; - } - } else { ---- linux-2.6.16.orig/drivers/media/video/vpx3220.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/vpx3220.c 2006-03-22 17:06:15.000000000 +0100 -@@ -30,7 +30,6 @@ - #include <asm/uaccess.h> - - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - - #define I2C_NAME(x) (x)->name - ---- linux-2.6.16.orig/sound/oss/dmasound/dmasound_awacs.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/sound/oss/dmasound/dmasound_awacs.c 2006-03-22 17:06:15.000000000 +0100 -@@ -88,8 +88,6 @@ - #include <linux/pmu.h> - #endif - --#include <linux/i2c-dev.h> -- - #include <asm/uaccess.h> - #include <asm/prom.h> - #include <asm/machdep.h> ---- linux-2.6.16.orig/sound/ppc/daca.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/sound/ppc/daca.c 2006-03-22 17:06:15.000000000 +0100 -@@ -22,7 +22,6 @@ - #include <sound/driver.h> - #include <linux/init.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <linux/kmod.h> - #include <linux/slab.h> - #include <sound/core.h> ---- linux-2.6.16.orig/sound/ppc/keywest.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/sound/ppc/keywest.c 2006-03-22 17:06:15.000000000 +0100 -@@ -23,7 +23,6 @@ - #include <linux/init.h> - #include <linux/i2c.h> - #include <linux/delay.h> --#include <linux/i2c-dev.h> - #include <linux/slab.h> - #include <sound/core.h> - #include "pmac.h" ---- linux-2.6.16.orig/sound/ppc/toonie.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/sound/ppc/toonie.c 2006-03-22 17:06:15.000000000 +0100 -@@ -22,7 +22,6 @@ - #include <linux/init.h> - #include <linux/delay.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <linux/kmod.h> - #include <linux/slab.h> - #include <linux/interrupt.h> ---- linux-2.6.16.orig/sound/ppc/tumbler.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/sound/ppc/tumbler.c 2006-03-22 17:06:15.000000000 +0100 -@@ -28,7 +28,6 @@ - #include <linux/init.h> - #include <linux/delay.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <linux/kmod.h> - #include <linux/slab.h> - #include <linux/interrupt.h> ---- linux-2.6.16.orig/drivers/hwmon/hwmon.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/hwmon.c 2006-03-22 17:06:15.000000000 +0100 -@@ -17,6 +17,7 @@ - #include <linux/idr.h> - #include <linux/hwmon.h> - #include <linux/gfp.h> -+#include <linux/spinlock.h> - - #define HWMON_ID_PREFIX "hwmon" - #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" -@@ -24,6 +25,7 @@ - static struct class *hwmon_class; - - static DEFINE_IDR(hwmon_idr); -+static DEFINE_SPINLOCK(idr_lock); - - /** - * hwmon_device_register - register w/ hwmon sysfs class -@@ -37,20 +39,30 @@ - struct class_device *hwmon_device_register(struct device *dev) - { - struct class_device *cdev; -- int id; -+ int id, err; - -- if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) -+again: -+ if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) - return ERR_PTR(-ENOMEM); - -- if (idr_get_new(&hwmon_idr, NULL, &id) < 0) -- return ERR_PTR(-ENOMEM); -+ spin_lock(&idr_lock); -+ err = idr_get_new(&hwmon_idr, NULL, &id); -+ spin_unlock(&idr_lock); -+ -+ if (unlikely(err == -EAGAIN)) -+ goto again; -+ else if (unlikely(err)) -+ return ERR_PTR(err); - - id = id & MAX_ID_MASK; - cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, - HWMON_ID_FORMAT, id); - -- if (IS_ERR(cdev)) -+ if (IS_ERR(cdev)) { -+ spin_lock(&idr_lock); - idr_remove(&hwmon_idr, id); -+ spin_unlock(&idr_lock); -+ } - - return cdev; - } -@@ -64,9 +76,11 @@ - { - int id; - -- if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { -+ if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { - class_device_unregister(cdev); -+ spin_lock(&idr_lock); - idr_remove(&hwmon_idr, id); -+ spin_unlock(&idr_lock); - } else - dev_dbg(cdev->dev, - "hwmon_device_unregister() failed: bad class ID!\n"); ---- linux-2.6.16.orig/arch/m68k/bvme6000/rtc.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/arch/m68k/bvme6000/rtc.c 2006-03-22 17:06:15.000000000 +0100 -@@ -18,6 +18,7 @@ - #include <linux/module.h> - #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ - #include <linux/smp_lock.h> -+#include <linux/bcd.h> - #include <asm/bvme6000hw.h> - - #include <asm/io.h> -@@ -32,9 +33,6 @@ - * ioctls. - */ - --#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) --#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) -- - static unsigned char days_in_mo[] = - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - ---- linux-2.6.16.orig/drivers/video/matrox/matroxfb_maven.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/video/matrox/matroxfb_maven.c 2006-03-22 17:06:15.000000000 +0100 -@@ -129,7 +129,7 @@ - - struct maven_data { - struct matrox_fb_info* primary_head; -- struct i2c_client* client; -+ struct i2c_client client; - int version; - }; - -@@ -970,7 +970,7 @@ - - static int maven_program_timming(struct maven_data* md, - const struct mavenregs* m) { -- struct i2c_client* c = md->client; -+ struct i2c_client* c = &md->client; - - if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { - LR(0x80); -@@ -1007,7 +1007,7 @@ - } - - static inline int maven_resync(struct maven_data* md) { -- struct i2c_client* c = md->client; -+ struct i2c_client* c = &md->client; - maven_set_reg(c, 0x95, 0x20); /* start whole thing */ - return 0; - } -@@ -1065,48 +1065,48 @@ - maven_compute_bwlevel(md, &blacklevel, &whitelevel); - blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); - whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); -- maven_set_reg_pair(md->client, 0x0e, blacklevel); -- maven_set_reg_pair(md->client, 0x1e, whitelevel); -+ maven_set_reg_pair(&md->client, 0x0e, blacklevel); -+ maven_set_reg_pair(&md->client, 0x1e, whitelevel); - } - break; - case V4L2_CID_SATURATION: - { -- maven_set_reg(md->client, 0x20, p->value); -- maven_set_reg(md->client, 0x22, p->value); -+ maven_set_reg(&md->client, 0x20, p->value); -+ maven_set_reg(&md->client, 0x22, p->value); - } - break; - case V4L2_CID_HUE: - { -- maven_set_reg(md->client, 0x25, p->value); -+ maven_set_reg(&md->client, 0x25, p->value); - } - break; - case V4L2_CID_GAMMA: - { - const struct maven_gamma* g; - g = maven_compute_gamma(md); -- maven_set_reg(md->client, 0x83, g->reg83); -- maven_set_reg(md->client, 0x84, g->reg84); -- maven_set_reg(md->client, 0x85, g->reg85); -- maven_set_reg(md->client, 0x86, g->reg86); -- maven_set_reg(md->client, 0x87, g->reg87); -- maven_set_reg(md->client, 0x88, g->reg88); -- maven_set_reg(md->client, 0x89, g->reg89); -- maven_set_reg(md->client, 0x8a, g->reg8a); -- maven_set_reg(md->client, 0x8b, g->reg8b); -+ maven_set_reg(&md->client, 0x83, g->reg83); -+ maven_set_reg(&md->client, 0x84, g->reg84); -+ maven_set_reg(&md->client, 0x85, g->reg85); -+ maven_set_reg(&md->client, 0x86, g->reg86); -+ maven_set_reg(&md->client, 0x87, g->reg87); -+ maven_set_reg(&md->client, 0x88, g->reg88); -+ maven_set_reg(&md->client, 0x89, g->reg89); -+ maven_set_reg(&md->client, 0x8a, g->reg8a); -+ maven_set_reg(&md->client, 0x8b, g->reg8b); - } - break; - case MATROXFB_CID_TESTOUT: - { - unsigned char val -- = maven_get_reg (md->client,0x8d); -+ = maven_get_reg(&md->client,0x8d); - if (p->value) val |= 0x10; - else val &= ~0x10; -- maven_set_reg (md->client, 0x8d, val); -+ maven_set_reg(&md->client, 0x8d, val); - } - break; - case MATROXFB_CID_DEFLICKER: - { -- maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); -+ maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); - } - break; - } -@@ -1185,7 +1185,6 @@ - MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); - - md->primary_head = MINFO; -- md->client = clnt; - down_write(&ACCESS_FBINFO(altout.lock)); - ACCESS_FBINFO(outputs[1]).output = &maven_altout; - ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; -@@ -1243,19 +1242,17 @@ - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_PROTOCOL_MANGLING)) - goto ERROR0; -- if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data), -- GFP_KERNEL))) { -+ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) { - err = -ENOMEM; - goto ERROR0; - } -- memset(new_client, 0, sizeof(*new_client) + sizeof(*data)); -- data = (struct maven_data*)(new_client + 1); -+ new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &maven_driver; - new_client->flags = 0; -- strcpy(new_client->name, "maven client"); -+ strlcpy(new_client->name, "maven", I2C_NAME_SIZE); - if ((err = i2c_attach_client(new_client))) - goto ERROR3; - err = maven_init_client(new_client); -@@ -1279,12 +1276,10 @@ - static int maven_detach_client(struct i2c_client* client) { - int err; - -- if ((err = i2c_detach_client(client))) { -- printk(KERN_ERR "maven: Cannot deregister client\n"); -+ if ((err = i2c_detach_client(client))) - return err; -- } - maven_shutdown_client(client); -- kfree(client); -+ kfree(i2c_get_clientdata(client)); - return 0; - } - -@@ -1297,20 +1292,13 @@ - .detach_client = maven_detach_client, - }; - --/* ************************** */ -- --static int matroxfb_maven_init(void) { -- int err; -- -- err = i2c_add_driver(&maven_driver); -- if (err) { -- printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err); -- return err; -- } -- return 0; -+static int __init matroxfb_maven_init(void) -+{ -+ return i2c_add_driver(&maven_driver); - } - --static void matroxfb_maven_exit(void) { -+static void __exit matroxfb_maven_exit(void) -+{ - i2c_del_driver(&maven_driver); - } - ---- linux-2.6.16.orig/drivers/macintosh/therm_pm72.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/macintosh/therm_pm72.c 2006-03-22 17:06:15.000000000 +0100 -@@ -104,7 +104,6 @@ - #include <linux/kernel.h> - #include <linux/delay.h> - #include <linux/sched.h> --#include <linux/i2c.h> - #include <linux/slab.h> - #include <linux/init.h> - #include <linux/spinlock.h> -@@ -113,7 +112,6 @@ - #include <linux/reboot.h> - #include <linux/kmod.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <asm/prom.h> - #include <asm/machdep.h> - #include <asm/io.h> ---- linux-2.6.16.orig/drivers/macintosh/windfarm_lm75_sensor.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/macintosh/windfarm_lm75_sensor.c 2006-03-22 17:06:15.000000000 +0100 -@@ -15,7 +15,6 @@ - #include <linux/init.h> - #include <linux/wait.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <asm/prom.h> - #include <asm/machdep.h> - #include <asm/io.h> ---- linux-2.6.16.orig/drivers/macintosh/windfarm_max6690_sensor.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/macintosh/windfarm_max6690_sensor.c 2006-03-22 17:06:15.000000000 +0100 -@@ -11,7 +11,6 @@ - #include <linux/init.h> - #include <linux/slab.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <asm/prom.h> - #include <asm/pmac_low_i2c.h> - ---- linux-2.6.16.orig/drivers/macintosh/windfarm_smu_sat.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/drivers/macintosh/windfarm_smu_sat.c 2006-03-22 17:06:15.000000000 +0100 -@@ -13,7 +13,6 @@ - #include <linux/init.h> - #include <linux/wait.h> - #include <linux/i2c.h> --#include <linux/i2c-dev.h> - #include <asm/semaphore.h> - #include <asm/prom.h> - #include <asm/smu.h> ---- linux-2.6.16.orig/arch/i386/kernel/traps.c 2006-03-22 17:06:08.000000000 +0100 -+++ linux-2.6.16/arch/i386/kernel/traps.c 2006-03-22 17:06:15.000000000 +0100 -@@ -166,8 +166,7 @@ - stack = (unsigned long*)context->previous_esp; - if (!stack) - break; -- printk(log_lvl); -- printk(" =======================\n"); -+ printk("%s =======================\n", log_lvl); - } - } - -@@ -196,14 +195,12 @@ - break; - if (i && ((i % 8) == 0)) { - printk("\n"); -- printk(log_lvl); -- printk(" "); -+ printk("%s ", log_lvl); - } - printk("%08lx ", *stack++); - } - printk("\n"); -- printk(log_lvl); -- printk("Call Trace:\n"); -+ printk("%sCall Trace:\n", log_lvl); - show_trace_log_lvl(task, esp, log_lvl); - } - ---- linux-2.6.16.orig/drivers/media/video/zoran_card.c 2006-03-22 17:06:07.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/zoran_card.c 2006-03-22 17:06:16.000000000 +0100 -@@ -452,6 +452,8 @@ - .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS, - .i2c_decoder = I2C_DRIVERID_SAA7110, - .i2c_encoder = I2C_DRIVERID_ADV7175, -+ .decoder_addr = 0x4e, -+ .encoder_addr = 0x2b, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 3, -@@ -995,10 +997,7 @@ - static int __devinit - zr36057_init (struct zoran *zr) - { -- u32 *mem; -- void *vdev; -- unsigned mem_needed; -- int j; -+ int j, err; - int two = 2; - int zero = 0; - -@@ -1049,19 +1048,16 @@ - - /* allocate memory *before* doing anything to the hardware - * in case allocation fails */ -- mem_needed = BUZ_NUM_STAT_COM * 4; -- mem = kzalloc(mem_needed, GFP_KERNEL); -- vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL); -- if (!mem || !vdev) { -+ zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); -+ zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL); -+ if (!zr->stat_com || !zr->video_dev) { - dprintk(1, - KERN_ERR - "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", - ZR_DEVNAME(zr)); -- kfree(vdev); -- kfree(mem); -- return -ENOMEM; -+ err = -ENOMEM; -+ goto exit_free; - } -- zr->stat_com = mem; - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ - } -@@ -1069,16 +1065,11 @@ - /* - * Now add the template and register the device unit. - */ -- zr->video_dev = vdev; - memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); - strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); -- if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER, -- video_nr) < 0) { -- zoran_unregister_i2c(zr); -- kfree((void *) zr->stat_com); -- kfree(vdev); -- return -1; -- } -+ err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); -+ if (err < 0) -+ goto exit_unregister; - - zoran_init_hardware(zr); - if (*zr_debug > 2) -@@ -1092,6 +1083,13 @@ - zr->zoran_proc = NULL; - zr->initialized = 1; - return 0; -+ -+exit_unregister: -+ zoran_unregister_i2c(zr); -+exit_free: -+ kfree(zr->stat_com); -+ kfree(zr->video_dev); -+ return err; - } - - static void -@@ -1121,7 +1119,7 @@ - btwrite(0, ZR36057_SPGPPCR); - free_irq(zr->pci_dev->irq, zr); - /* unmap and free memory */ -- kfree((void *) zr->stat_com); -+ kfree(zr->stat_com); - zoran_proc_cleanup(zr); - iounmap(zr->zr36057_mem); - pci_disable_device(zr->pci_dev); -@@ -1349,6 +1347,14 @@ - i2c_dec_name = NULL; - } - -+ if (zoran_register_i2c(zr) < 0) { -+ dprintk(1, -+ KERN_ERR -+ "%s: find_zr36057() - can't initialize i2c bus\n", -+ ZR_DEVNAME(zr)); -+ goto zr_free_irq; -+ } -+ - if (i2c_dec_name) { - if ((result = request_module(i2c_dec_name)) < 0) { - dprintk(1, -@@ -1356,6 +1362,10 @@ - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_dec_name, result); - } -+ -+ i2c_probe_device(&zr->i2c_adapter, -+ zr->card.i2c_decoder, -+ zr->card.decoder_addr, 0); - } - - /* i2c encoder */ -@@ -1376,14 +1386,10 @@ - "%s: failed to load module %s: %d\n", - ZR_DEVNAME(zr), i2c_enc_name, result); - } -- } - -- if (zoran_register_i2c(zr) < 0) { -- dprintk(1, -- KERN_ERR -- "%s: find_zr36057() - can't initialize i2c bus\n", -- ZR_DEVNAME(zr)); -- goto zr_free_irq; -+ i2c_probe_device(&zr->i2c_adapter, -+ zr->card.i2c_encoder, -+ zr->card.encoder_addr, 0); - } - - dprintk(2, ---- linux-2.6.16.orig/Documentation/hwmon/lm83 2006-03-22 17:06:07.000000000 +0100 -+++ linux-2.6.16/Documentation/hwmon/lm83 2006-03-22 17:06:16.000000000 +0100 -@@ -7,6 +7,10 @@ - Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e - Datasheet: Publicly available at the National Semiconductor website - http://www.national.com/pf/LM/LM83.html -+ * National Semiconductor LM82 -+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e -+ Datasheet: Publicly available at the National Semiconductor website -+ http://www.national.com/pf/LM/LM82.html - - - Author: Jean Delvare <khali@linux-fr.org> -@@ -15,10 +19,11 @@ - ----------- - - The LM83 is a digital temperature sensor. It senses its own temperature as --well as the temperature of up to three external diodes. It is compatible --with many other devices such as the LM84 and all other ADM1021 clones. --The main difference between the LM83 and the LM84 in that the later can --only sense the temperature of one external diode. -+well as the temperature of up to three external diodes. The LM82 is -+a stripped down version of the LM83 that only supports one external diode. -+Both are compatible with many other devices such as the LM84 and all -+other ADM1021 clones. The main difference between the LM83 and the LM84 -+in that the later can only sense the temperature of one external diode. - - Using the adm1021 driver for a LM83 should work, but only two temperatures - will be reported instead of four. -@@ -36,6 +41,9 @@ - Iwill MPX2 - Soltek SL-75DRV5 - -+The LM82 is confirmed to have been found on most AMD Geode reference -+designs and test platforms. -+ - The driver has been successfully tested by Magnus Forsström, who I'd - like to thank here. More testers will be of course welcome. - ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.16/Documentation/hwmon/smsc47m192 2006-03-22 17:06:16.000000000 +0100 -@@ -0,0 +1,102 @@ -+Kernel driver smsc47m192 -+======================== -+ -+Supported chips: -+ * SMSC LPC47M192 and LPC47M997 -+ Prefix: 'smsc47m192' -+ Addresses scanned: I2C 0x2c - 0x2d -+ Datasheet: The datasheet for LPC47M192 is publicly available from -+ http://www.smsc.com/ -+ The LPC47M997 is compatible for hardware monitoring. -+ -+Author: Hartmut Rick <linux@rick.claranet.de> -+ Special thanks to Jean Delvare for careful checking -+ of the code and many helpful comments and suggestions. -+ -+ -+Description -+----------- -+ -+This driver implements support for the hardware sensor capabilities -+of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. -+ -+These chips support 3 temperature channels and 8 voltage inputs -+as well as CPU voltage VID input. -+ -+They do also have fan monitoring and control capabilities, but the -+these features are accessed via ISA bus and are not supported by this -+driver. Use the 'smsc47m1' driver for fan monitoring and control. -+ -+Voltages and temperatures are measured by an 8-bit ADC, the resolution -+of the temperatures is 1 bit per degree C. -+Voltages are scaled such that the nominal voltage corresponds to -+192 counts, i.e. 3/4 of the full range. Thus the available range for -+each voltage channel is 0V ... 255/192*(nominal voltage), the resolution -+is 1 bit per (nominal voltage)/192. -+Both voltage and temperature values are scaled by 1000, the sys files -+show voltages in mV and temperatures in units of 0.001 degC. -+ -+The +12V analog voltage input channel (in4_input) is multiplexed with -+bit 4 of the encoded CPU voltage. This means that you either get -+a +12V voltage measurement or a 5 bit CPU VID, but not both. -+The default setting is to use the pin as 12V input, and use only 4 bit VID. -+This driver assumes that the information in the configuration register -+is correct, i.e. that the BIOS has updated the configuration if -+the motherboard has this input wired to VID4. -+ -+The temperature and voltage readings are updated once every 1.5 seconds. -+Reading them more often repeats the same values. -+ -+ -+sysfs interface -+--------------- -+ -+in0_input - +2.5V voltage input -+in1_input - CPU voltage input (nominal 2.25V) -+in2_input - +3.3V voltage input -+in3_input - +5V voltage input -+in4_input - +12V voltage input (may be missing if used as VID4) -+in5_input - Vcc voltage input (nominal 3.3V) -+ This is the supply voltage of the sensor chip itself. -+in6_input - +1.5V voltage input -+in7_input - +1.8V voltage input -+ -+in[0-7]_min, -+in[0-7]_max - lower and upper alarm thresholds for in[0-7]_input reading -+ -+ All voltages are read and written in mV. -+ -+in[0-7]_alarm - alarm flags for voltage inputs -+ These files read '1' in case of alarm, '0' otherwise. -+ -+temp1_input - chip temperature measured by on-chip diode -+temp[2-3]_input - temperature measured by external diodes (one of these would -+ typically be wired to the diode inside the CPU) -+ -+temp[1-3]_min, -+temp[1-3]_max - lower and upper alarm thresholds for temperatures -+ -+temp[1-3]_offset - temperature offset registers -+ The chip adds the offsets stored in these registers to -+ the corresponding temperature readings. -+ Note that temp1 and temp2 offsets share the same register, -+ they cannot both be different from zero at the same time. -+ Writing a non-zero number to one of them will reset the other -+ offset to zero. -+ -+ All temperatures and offsets are read and written in -+ units of 0.001 degC. -+ -+temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm, -+ '0' otherwise. -+temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3. -+ A fault is detected if the two pins for the corresponding -+ sensor are open or shorted, or any of the two is shorted -+ to ground or Vcc. '1' indicates a diode fault. -+ -+cpu0_vid - CPU voltage as received from the CPU -+ -+vrm - CPU VID standard used for decoding CPU voltage -+ -+ The *_min, *_max, *_offset and vrm files can be read and -+ written, all others are read-only. ---- linux-2.6.16.orig/Documentation/hwmon/sysfs-interface 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/Documentation/hwmon/sysfs-interface 2006-03-22 17:06:16.000000000 +0100 -@@ -218,6 +218,12 @@ - from the critical value. - Read/Write value. - -+temp[1-4]_offset -+ Temperature offset which is added to the temperature reading -+ by the chip. -+ Unit: millidegree Celsius -+ Read/Write value. -+ - If there are multiple temperature sensors, temp1_* is - generally the sensor inside the chip itself, - reported as "motherboard temperature". temp2_* to -@@ -246,9 +252,68 @@ - Read only. - - --********* --* Other * --********* -+********** -+* Alarms * -+********** -+ -+Each channel or limit may have an associated alarm file, containing a -+boolean value. 1 means than an alarm condition exists, 0 means no alarm. -+ -+Usually a given chip will either use channel-related alarms, or -+limit-related alarms, not both. The driver should just reflect the hardware -+implementation. -+ -+in[0-n]_alarm -+fan[1-n]_alarm -+temp[1-n]_alarm -+ Channel alarm -+ Boolean -+ Read-only -+ -+OR -+ -+in[0-n]_min_alarm -+in[0-n]_max_alarm -+fan[1-n]_min_alarm -+temp[1-n]_min_alarm -+temp[1-n]_max_alarm -+temp[1-n]_crit_alarm -+ Limit alarm -+ Boolean -+ Read-only -+ -+In theory, a chip could provide per-limit beep masking, but no such chip -+was seen so far. -+ -+Each input channel may have an associated fault file. This can be used -+to notify open diodes, unconnected fans etc. where the hardware -+supports it. When this boolean has value 1, the measurement for that -+channel should not be trusted. -+ -+fan[1-n]_input_fault -+temp[1-n]_input_fault -+ Input fault condition -+ Boolean -+ Read-only -+ -+Some chips also offer the possibility to get beeped when an alarm occurs: -+ -+beep_enable Master beep enable -+ 0 to disable. -+ 1 to enable. -+ Read/Write -+ -+in[0-n]_beep -+fan[1-n]_beep -+temp[1-n]_beep -+ Channel beep -+ 0 to disable. -+ 1 to enable. -+ Read/write -+ -+Old drivers provided a different, non-standard interface to alarms and -+beeps. These interface files are deprecated, but will be kept around -+for compatibility reasons: - - alarms Alarm bitmask. - Read only. -@@ -259,33 +324,22 @@ - 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. -+ of individual bits. For this reason, the use of this -+ interface file for new drivers is discouraged. Use -+ individual *_alarm and *_fault files instead. - Bits are defined in kernel/include/sensors.h. - --alarms_in Alarm bitmask relative to in (voltage) channels -- Read only -- A '1' bit means an alarm, LSB corresponds to in0 and so on -- Prefered to 'alarms' for newer chips -- --alarms_fan Alarm bitmask relative to fan channels -- Read only -- A '1' bit means an alarm, LSB corresponds to fan1 and so on -- Prefered to 'alarms' for newer chips -- --alarms_temp Alarm bitmask relative to temp (temperature) channels -- Read only -- A '1' bit means an alarm, LSB corresponds to temp1 and so on -- Prefered to 'alarms' for newer chips -- --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. -+ Same format as 'alarms' with the same bit locations, -+ use discouraged for the same reason. Use individual -+ *_beep files instead. - Read/Write - -+ -+********* -+* Other * -+********* -+ - eeprom Raw EEPROM data in binary form. - Read only. - ---- linux-2.6.16.orig/drivers/hwmon/Makefile 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/drivers/hwmon/Makefile 2006-03-22 17:06:16.000000000 +0100 -@@ -40,6 +40,7 @@ - obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o - obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o - obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o -+obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o - obj-$(CONFIG_SENSORS_VIA686A) += via686a.o - obj-$(CONFIG_SENSORS_VT8231) += vt8231.o - obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.16/drivers/hwmon/smsc47m192.c 2006-03-22 17:06:16.000000000 +0100 -@@ -0,0 +1,638 @@ -+/* -+ smsc47m192.c - Support for hardware monitoring block of -+ SMSC LPC47M192 and LPC47M997 Super I/O chips -+ -+ Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> -+ -+ Derived from lm78.c and other chip drivers. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/slab.h> -+#include <linux/jiffies.h> -+#include <linux/i2c.h> -+#include <linux/hwmon.h> -+#include <linux/hwmon-sysfs.h> -+#include <linux/hwmon-vid.h> -+#include <linux/err.h> -+ -+/* Addresses to scan */ -+static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD_1(smsc47m192); -+ -+/* SMSC47M192 registers */ -+#define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ -+ (0x50 + (nr) - 6)) -+#define SMSC47M192_REG_IN_MAX(nr) ((nr)<6 ? (0x2b + (nr) * 2) : \ -+ (0x54 + (((nr) - 6) * 2))) -+#define SMSC47M192_REG_IN_MIN(nr) ((nr)<6 ? (0x2c + (nr) * 2) : \ -+ (0x55 + (((nr) - 6) * 2))) -+static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; -+static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; -+static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; -+#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f) -+#define SMSC47M192_REG_ALARM1 0x41 -+#define SMSC47M192_REG_ALARM2 0x42 -+#define SMSC47M192_REG_VID 0x47 -+#define SMSC47M192_REG_VID4 0x49 -+#define SMSC47M192_REG_CONFIG 0x40 -+#define SMSC47M192_REG_SFR 0x4f -+#define SMSC47M192_REG_COMPANY_ID 0x3e -+#define SMSC47M192_REG_VERSION 0x3f -+ -+/* generalised scaling with integer rounding */ -+static inline int SCALE(long val, int mul, int div) -+{ -+ if (val < 0) -+ return (val * mul - div / 2) / div; -+ else -+ return (val * mul + div / 2) / div; -+} -+ -+/* Conversions */ -+ -+/* smsc47m192 internally scales voltage measurements */ -+static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; -+ -+static inline unsigned int IN_FROM_REG(u8 reg, int n) -+{ -+ return SCALE(reg, nom_mv[n], 192); -+} -+ -+static inline u8 IN_TO_REG(unsigned long val, int n) -+{ -+ return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); -+} -+ -+/* TEMP: 0.001 degC units (-128C to +127C) -+ REG: 1C/bit, two's complement */ -+static inline s8 TEMP_TO_REG(int val) -+{ -+ return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); -+} -+ -+static inline int TEMP_FROM_REG(s8 val) -+{ -+ return val * 1000; -+} -+ -+struct smsc47m192_data { -+ struct i2c_client client; -+ struct class_device *class_dev; -+ struct semaphore update_lock; -+ char valid; /* !=0 if following fields are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ -+ u8 in[8]; /* Register value */ -+ u8 in_max[8]; /* Register value */ -+ u8 in_min[8]; /* Register value */ -+ s8 temp[3]; /* Register value */ -+ s8 temp_max[3]; /* Register value */ -+ s8 temp_min[3]; /* Register value */ -+ s8 temp_offset[3]; /* Register value */ -+ u16 alarms; /* Register encoding, combined */ -+ u8 vid; /* Register encoding, combined */ -+ u8 vrm; -+}; -+ -+static int smsc47m192_detect(struct i2c_adapter *adapter, int address, -+ int kind); -+static int smsc47m192_detach_client(struct i2c_client *client); -+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); -+ -+static struct i2c_driver smsc47m192_driver = { -+ .driver = { -+ .name = "smsc47m192", -+ }, -+ .class = I2C_CLASS_HWMON, -+ .address_data = &addr_data, -+ .detect_client = smsc47m192_detect, -+ .detach_client = smsc47m192_detach_client, -+}; -+ -+/* Voltages */ -+static ssize_t show_in(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); -+} -+ -+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); -+} -+ -+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); -+} -+ -+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ unsigned long val = simple_strtoul(buf, NULL, 10); -+ -+ down(&data->update_lock); -+ data->in_min[nr] = IN_TO_REG(val, nr); -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), -+ data->in_min[nr]); -+ up(&data->update_lock); -+ return count; -+} -+ -+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ unsigned long val = simple_strtoul(buf, NULL, 10); -+ -+ down(&data->update_lock); -+ data->in_max[nr] = IN_TO_REG(val, nr); -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), -+ data->in_max[nr]); -+ up(&data->update_lock); -+ return count; -+} -+ -+#define show_in_offset(offset) \ -+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ -+ show_in, NULL, offset); \ -+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ -+ show_in_min, set_in_min, offset); \ -+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ -+ show_in_max, set_in_max, offset); -+ -+show_in_offset(0) -+show_in_offset(1) -+show_in_offset(2) -+show_in_offset(3) -+show_in_offset(4) -+show_in_offset(5) -+show_in_offset(6) -+show_in_offset(7) -+ -+/* Temperatures */ -+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -+} -+ -+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); -+} -+ -+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); -+} -+ -+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ long val = simple_strtol(buf, NULL, 10); -+ -+ down(&data->update_lock); -+ data->temp_min[nr] = TEMP_TO_REG(val); -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], -+ data->temp_min[nr]); -+ up(&data->update_lock); -+ return count; -+} -+ -+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ long val = simple_strtol(buf, NULL, 10); -+ -+ down(&data->update_lock); -+ data->temp_max[nr] = TEMP_TO_REG(val); -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], -+ data->temp_max[nr]); -+ up(&data->update_lock); -+ return count; -+} -+ -+static ssize_t show_temp_offset(struct device *dev, struct device_attribute -+ *attr, char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); -+} -+ -+static ssize_t set_temp_offset(struct device *dev, struct device_attribute -+ *attr, const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); -+ long val = simple_strtol(buf, NULL, 10); -+ -+ down(&data->update_lock); -+ data->temp_offset[nr] = TEMP_TO_REG(val); -+ if (nr>1) -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); -+ else if (data->temp_offset[nr] != 0) { -+ /* offset[0] and offset[1] share the same register, -+ SFR bit 4 activates offset[0] */ -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, -+ (sfr & 0xef) | (nr==0 ? 0x10 : 0)); -+ data->temp_offset[1-nr] = 0; -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); -+ } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_TEMP_OFFSET(nr), 0); -+ up(&data->update_lock); -+ return count; -+} -+ -+#define show_temp_index(index) \ -+static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ -+ show_temp, NULL, index-1); \ -+static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ -+ show_temp_min, set_temp_min, index-1); \ -+static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ -+ show_temp_max, set_temp_max, index-1); \ -+static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ -+ show_temp_offset, set_temp_offset, index-1); -+ -+show_temp_index(1) -+show_temp_index(2) -+show_temp_index(3) -+ -+/* VID */ -+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -+} -+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); -+ -+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%d\n", data->vrm); -+} -+ -+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ data->vrm = simple_strtoul(buf, NULL, 10); -+ return count; -+} -+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); -+ -+/* Alarms */ -+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); -+ int nr = sensor_attr->index; -+ struct smsc47m192_data *data = smsc47m192_update_device(dev); -+ return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); -+} -+ -+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); -+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); -+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); -+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); -+static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); -+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); -+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); -+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); -+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); -+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); -+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); -+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); -+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); -+ -+static void smsc47m192_init_client(struct i2c_client *client) -+{ -+ int i; -+ u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); -+ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); -+ -+ /* select cycle mode (pause 1 sec between updates) */ -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, -+ (sfr & 0xfd) | 0x02); -+ if (!(config & 0x01)) { -+ /* initialize alarm limits */ -+ for (i=0; i<8; i++) { -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_IN_MIN(i), 0); -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_IN_MAX(i), 0xff); -+ } -+ for (i=0; i<3; i++) { -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_TEMP_MIN[i], 0x80); -+ i2c_smbus_write_byte_data(client, -+ SMSC47M192_REG_TEMP_MAX[i], 0x7f); -+ } -+ -+ /* start monitoring */ -+ i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, -+ (config & 0xf7) | 0x01); -+ } -+} -+ -+/* This function is called by i2c_probe */ -+static int smsc47m192_detect(struct i2c_adapter *adapter, int address, -+ int kind) -+{ -+ struct i2c_client *client; -+ struct smsc47m192_data *data; -+ int err = 0; -+ int version, config; -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -+ goto exit; -+ -+ if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ client = &data->client; -+ i2c_set_clientdata(client, data); -+ client->addr = address; -+ client->adapter = adapter; -+ client->driver = &smsc47m192_driver; -+ -+ if (kind == 0) -+ kind = smsc47m192; -+ -+ /* Detection criteria from sensors_detect script */ -+ if (kind < 0) { -+ if (i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_COMPANY_ID) == 0x55 -+ && ((version = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 -+ && (i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_VID) & 0x70) == 0x00 -+ && (i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_VID4) & 0xfe) == 0x80) { -+ dev_info(&adapter->dev, -+ "found SMSC47M192 or SMSC47M997, " -+ "version 2, stepping A%d\n", version & 0x0f); -+ } else { -+ dev_dbg(&adapter->dev, -+ "SMSC47M192 detection failed at 0x%02x\n", -+ address); -+ goto exit_free; -+ } -+ } -+ -+ /* Fill in the remaining client fields and put into the global list */ -+ strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); -+ data->vrm = vid_which_vrm(); -+ init_MUTEX(&data->update_lock); -+ -+ /* Tell the I2C layer a new client has arrived */ -+ if ((err = i2c_attach_client(client))) -+ goto exit_free; -+ -+ /* Initialize the SMSC47M192 chip */ -+ smsc47m192_init_client(client); -+ -+ /* Register sysfs hooks */ -+ data->class_dev = hwmon_device_register(&client->dev); -+ if (IS_ERR(data->class_dev)) { -+ err = PTR_ERR(data->class_dev); -+ goto exit_detach; -+ } -+ -+ device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); -+ -+ /* Pin 110 is either in4 (+12V) or VID4 */ -+ config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); -+ if (!(config & 0x20)) { -+ device_create_file(&client->dev, -+ &sensor_dev_attr_in4_input.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_in4_min.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_in4_max.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_in4_alarm.dev_attr); -+ } -+ device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_temp1_offset.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_temp2_offset.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_temp2_input_fault.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_temp3_offset.dev_attr); -+ device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); -+ device_create_file(&client->dev, -+ &sensor_dev_attr_temp3_input_fault.dev_attr); -+ device_create_file(&client->dev, &dev_attr_cpu0_vid); -+ device_create_file(&client->dev, &dev_attr_vrm); -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(client); -+exit_free: -+ kfree(data); -+exit: -+ return err; -+} -+ -+static int smsc47m192_detach_client(struct i2c_client *client) -+{ -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ int err; -+ -+ hwmon_device_unregister(data->class_dev); -+ -+ if ((err = i2c_detach_client(client))) -+ return err; -+ -+ kfree(data); -+ -+ return 0; -+} -+ -+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct smsc47m192_data *data = i2c_get_clientdata(client); -+ int i, config; -+ -+ down(&data->update_lock); -+ -+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) -+ || !data->valid) { -+ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); -+ -+ dev_dbg(&client->dev, "Starting smsc47m192 update\n"); -+ -+ for (i = 0; i <= 7; i++) { -+ data->in[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_IN(i)); -+ data->in_min[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_IN_MIN(i)); -+ data->in_max[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_IN_MAX(i)); -+ } -+ for (i = 0; i < 3; i++) { -+ data->temp[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_TEMP[i]); -+ data->temp_max[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_TEMP_MAX[i]); -+ data->temp_min[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_TEMP_MIN[i]); -+ } -+ for (i = 1; i < 3; i++) -+ data->temp_offset[i] = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_TEMP_OFFSET(i)); -+ /* first offset is temp_offset[0] if SFR bit 4 is set, -+ temp_offset[1] otherwise */ -+ if (sfr & 0x10) { -+ data->temp_offset[0] = data->temp_offset[1]; -+ data->temp_offset[1] = 0; -+ } else -+ data->temp_offset[0] = 0; -+ -+ data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) -+ & 0x0f; -+ config = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_CONFIG); -+ if (config & 0x20) -+ data->vid |= (i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_VID4) & 0x01) << 4; -+ data->alarms = i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_ALARM1) | -+ (i2c_smbus_read_byte_data(client, -+ SMSC47M192_REG_ALARM2) << 8); -+ -+ data->last_updated = jiffies; -+ data->valid = 1; -+ } -+ -+ up(&data->update_lock); -+ -+ return data; -+} -+ -+static int __init smsc47m192_init(void) -+{ -+ return i2c_add_driver(&smsc47m192_driver); -+} -+ -+static void __exit smsc47m192_exit(void) -+{ -+ i2c_del_driver(&smsc47m192_driver); -+} -+ -+MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>"); -+MODULE_DESCRIPTION("SMSC47M192 driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(smsc47m192_init); -+module_exit(smsc47m192_exit); ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis96x.c 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-sis96x.c 2006-03-22 17:06:16.000000000 +0100 -@@ -43,13 +43,6 @@ - #include <linux/init.h> - #include <asm/io.h> - --/* -- HISTORY: -- 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5 -- (was i2c-sis645.c from lm_sensors 2.7.0) --*/ --#define SIS96x_VERSION "1.0.0" -- - /* base address register in PCI config space */ - #define SIS96x_BAR 0x04 - -@@ -256,7 +249,7 @@ - - static struct i2c_adapter sis96x_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - -@@ -337,7 +330,6 @@ - - static int __init i2c_sis96x_init(void) - { -- printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION); - return pci_register_driver(&sis96x_driver); - } - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport-light.c 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-parport-light.c 2006-03-22 17:06:16.000000000 +0100 -@@ -111,7 +111,7 @@ - - static struct i2c_adapter parport_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .id = I2C_HW_B_LP, - .algo_data = &parport_algo_data, - .name = "Parallel port adapter (light)", -@@ -121,9 +121,14 @@ - - static int __init i2c_parport_init(void) - { -- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { -+ if (type < 0) { -+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); -+ return -ENODEV; -+ } -+ -+ if (type >= ARRAY_SIZE(adapter_parm)) { - printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); -- type = 0; -+ return -ENODEV; - } - - if (base == 0) { ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport.h 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-parport.h 2006-03-22 17:06:16.000000000 +0100 -@@ -90,7 +90,7 @@ - }, - }; - --static int type; -+static int type = -1; - module_param(type, int, 0); - MODULE_PARM_DESC(type, - "Type of adapter:\n" ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport.c 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-parport.c 2006-03-22 17:06:16.000000000 +0100 -@@ -146,7 +146,7 @@ - - static struct i2c_adapter parport_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .id = I2C_HW_B_LP, - .name = "Parallel port adapter", - }; -@@ -241,9 +241,14 @@ - - static int __init i2c_parport_init(void) - { -- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { -+ if (type < 0) { -+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); -+ return -ENODEV; -+ } -+ -+ if (type >= ARRAY_SIZE(adapter_parm)) { - printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); -- type = 0; -+ return -ENODEV; - } - - return parport_register_driver(&i2c_parport_driver); ---- linux-2.6.16.orig/Documentation/i2c/busses/i2c-parport 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/Documentation/i2c/busses/i2c-parport 2006-03-22 17:06:16.000000000 +0100 -@@ -12,18 +12,22 @@ - teletext adapters) - - It currently supports the following devices: -- * Philips adapter -- * home brew teletext adapter -- * Velleman K8000 adapter -- * ELV adapter -- * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032) -- * Barco LPT->DVI (K5800236) adapter -+ * (type=0) Philips adapter -+ * (type=1) home brew teletext adapter -+ * (type=2) Velleman K8000 adapter -+ * (type=3) ELV adapter -+ * (type=4) Analog Devices ADM1032 evaluation board -+ * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031 -+ * (type=6) Barco LPT->DVI (K5800236) adapter - - These devices use different pinout configurations, so you have to tell - the driver what you have, using the type module parameter. There is no - way to autodetect the devices. Support for different pinout configurations - can be easily added when needed. - -+Earlier kernels defaulted to type=0 (Philips). But now, if the type -+parameter is missing, the driver will simply fail to initialize. -+ - - Building your own adapter - ------------------------- ---- linux-2.6.16.orig/Documentation/i2c/writing-clients 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/Documentation/i2c/writing-clients 2006-03-22 17:06:16.000000000 +0100 -@@ -28,7 +28,9 @@ - .driver = { - .name = "foo", - }, -- .attach_adapter = &foo_attach_adapter, -+ .class = I2C_CLASS_SOMETHING, -+ .address_data = &addr_data, -+ .detect_client = &foo_detect_client, - .detach_client = &foo_detach_client, - .command = &foo_command /* may be NULL */ - } -@@ -141,8 +143,8 @@ - are defined in i2c.h to help you support them, as well as a generic - detection algorithm. - --You do not have to use this parameter interface; but don't try to use --function i2c_probe() if you don't. -+You do not have to use this parameter interface; but then the i2c core won't -+be able to probe for devices for you. - - NOTE: If you want to write a `sensors' driver, the interface is slightly - different! See below. -@@ -201,35 +203,49 @@ - ----------------------- - - Whenever a new adapter is inserted, or for all adapters if the driver is --being registered, the callback attach_adapter() is called. Now is the --time to determine what devices are present on the adapter, and to register --a client for each of them. -- --The attach_adapter callback is really easy: we just call the generic --detection function. This function will scan the bus for us, using the --information as defined in the lists explained above. If a device is --detected at a specific address, another callback is called. -+being registered, your driver may be notified through one of two -+callbacks, depending on the degree of control you need to exercise over -+the probing process. This is the time to determine what devices are -+present on the adapter and to register a client for each device your -+driver supports. -+ -+The easiest way to handle the probing process is to simply set the `class', -+`address_data', and `detect_client' fields in the i2c_driver structure. -+The `class' field is a bitmask of all the adapter classes which should be -+probed for devices supported by this driver. You should set it to one of -+the I2C_CLASS_* constants defined in i2c.h. The `address_data' field -+should be set to `&addr_data', which is defined by the macros explained -+above, so you do not have to define it yourself. When a new adapter is -+attached, the bus is scanned for the addresses defined in the lists above, -+and the detect_client callback gets called when a device is detected at a -+specific address. -+ -+If you prefer, you can omit the `class', `address_data', and -+`detect_client' fields from your i2c_driver structure, and instead set -+`attach_adapter'. The `attach_adapter' callback gets called every time a -+new adapter is attached and the bus needs to be scanned, so if you need to -+perform any special checks or configuration before you scan a bus for -+devices, you should use attach_adapter. If the bus is suitable, you can -+then call the generic i2c_probe function to scan for the addresses in the -+lists explained above, and the callback passed in the third parameter will -+get called for each device detected. - - int foo_attach_adapter(struct i2c_adapter *adapter) - { - return i2c_probe(adapter,&addr_data,&foo_detect_client); - } - --Remember, structure `addr_data' is defined by the macros explained above, --so you do not have to define it yourself. -- --The i2c_probe function will call the foo_detect_client --function only for those i2c addresses that actually have a device on --them (unless a `force' parameter was used). In addition, addresses that --are already in use (by some other registered client) are skipped. -+With either mechanism, addresses that are already in use (by some other -+registered client) are skipped. - - - The detect client function - -------------------------- - --The detect client function is called by i2c_probe. The `kind' parameter --contains -1 for a probed detection, 0 for a forced detection, or a positive --number for a forced detection with a chip type forced. -+The detect client function is called by the address probing mechanism. -+The `kind' parameter contains -1 for a probed detection, 0 for a forced -+detection, or a positive number for a forced detection with a chip type -+forced. - - Below, some things are only needed if this is a `sensors' driver. Those - parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */ ---- linux-2.6.16.orig/Documentation/i2c/porting-clients 2006-03-22 17:06:00.000000000 +0100 -+++ linux-2.6.16/Documentation/i2c/porting-clients 2006-03-22 17:06:16.000000000 +0100 -@@ -100,6 +100,9 @@ - Drop any 24RF08 corruption prevention you find, as this is now done - at the i2c-core level, and doing it twice voids it. - Don't add I2C_CLIENT_ALLOW_USE to client->flags, it's the default now. -+ If you want auto probing of your driver, use driver->addr_data -+ (this is strongly encouraged if your attach_adapter is a one-liner -+ which calls i2c_probe). - - * [Init] Limits must not be set by the driver (can be done later in - user-space). Chip should not be reset default (although a module ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali1563.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ali1563.c 2006-03-22 17:06:16.000000000 +0100 -@@ -374,7 +374,7 @@ - - static struct i2c_adapter ali1563_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &ali1563_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali15x3.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ali15x3.c 2006-03-22 17:06:16.000000000 +0100 -@@ -470,7 +470,7 @@ - - static struct i2c_adapter ali15x3_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd756.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-amd756.c 2006-03-22 17:06:16.000000000 +0100 -@@ -301,7 +301,7 @@ - - struct i2c_adapter amd756_smbus = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd8111.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-amd8111.c 2006-03-22 17:06:16.000000000 +0100 -@@ -351,7 +351,7 @@ - smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, I2C_NAME_SIZE, - "SMBus2 AMD8111 adapter at %04x", smbus->base); -- smbus->adapter.class = I2C_CLASS_HWMON; -+ smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-elektor.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-elektor.c 2006-03-22 17:06:16.000000000 +0100 -@@ -202,7 +202,7 @@ - - static struct i2c_adapter pcf_isa_ops = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .id = I2C_HW_P_ELEK, - .algo_data = &pcf_isa_data, - .name = "i2c-elektor", ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-i801.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-i801.c 2006-03-22 17:06:16.000000000 +0100 -@@ -513,7 +513,7 @@ - - static struct i2c_adapter i801_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-i810.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-i810.c 2006-03-22 17:06:16.000000000 +0100 -@@ -188,6 +188,7 @@ - - static struct i2c_adapter i810_ddc_adapter = { - .owner = THIS_MODULE, -+ .class = I2C_CLASS_DATA, - .name = "I810/I815 DDC Adapter", - .algo_data = &i810_ddc_bit_data, - }; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ibm_iic.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ibm_iic.c 2006-03-22 17:06:16.000000000 +0100 -@@ -724,8 +724,9 @@ - adap = &dev->adap; - strcpy(adap->name, "IBM IIC"); - i2c_set_adapdata(adap, dev); -+ adap->owner = THIS_MODULE; - adap->id = I2C_HW_OCP; -- adap->class = I2C_CLASS_HWMON; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DATA; - adap->algo = &iic_algo; - adap->client_register = NULL; - adap->client_unregister = NULL; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-ixp2000.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-ixp2000.c 2006-03-22 17:06:16.000000000 +0100 -@@ -117,7 +117,9 @@ - drv_data->algo_data.mdelay = 6; - drv_data->algo_data.timeout = 100; - -- drv_data->adapter.id = I2C_HW_B_IXP2000, -+ drv_data->adapter.owner = THIS_MODULE; -+ drv_data->adapter.class = I2C_CLASS_DATA; -+ drv_data->adapter.id = I2C_HW_B_IXP2000; - strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, - I2C_NAME_SIZE); - drv_data->adapter.algo_data = &drv_data->algo_data, ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-mpc.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-mpc.c 2006-03-22 17:06:16.000000000 +0100 -@@ -283,7 +283,7 @@ - .name = "MPC adapter", - .id = I2C_HW_MPC107, - .algo = &mpc_algo, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .timeout = 1, - .retries = 1 - }; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-mv64xxx.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-mv64xxx.c 2006-03-22 17:06:16.000000000 +0100 -@@ -519,7 +519,7 @@ - drv_data->adapter.id = I2C_HW_MV64XXX; - drv_data->adapter.algo = &mv64xxx_i2c_algo; - drv_data->adapter.owner = THIS_MODULE; -- drv_data->adapter.class = I2C_CLASS_HWMON; -+ drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; - drv_data->adapter.timeout = pdata->timeout; - drv_data->adapter.retries = pdata->retries; - platform_set_drvdata(pd, drv_data); ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-nforce2.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-nforce2.c 2006-03-22 17:06:16.000000000 +0100 -@@ -113,7 +113,7 @@ - - static struct i2c_adapter nforce2_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-prosavage.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-prosavage.c 2006-03-22 17:06:16.000000000 +0100 -@@ -172,6 +172,7 @@ - { - int ret; - p->adap.owner = THIS_MODULE; -+ p->adap.class = I2C_CLASS_DATA; - p->adap.id = I2C_HW_B_S3VIA; - p->adap.algo_data = &p->algo; - p->adap.dev.parent = &dev->dev; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-s3c2410.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-s3c2410.c 2006-03-22 17:06:16.000000000 +0100 -@@ -580,7 +580,7 @@ - .owner = THIS_MODULE, - .algo = &s3c24xx_i2c_algorithm, - .retries = 2, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - }, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-savage4.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-savage4.c 2006-03-22 17:06:16.000000000 +0100 -@@ -146,6 +146,7 @@ - - static struct i2c_adapter savage4_i2c_adapter = { - .owner = THIS_MODULE, -+ .class = I2C_CLASS_DATA, - .name = "I2C Savage4 adapter", - .algo_data = &sav_i2c_bit_data, - }; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-sibyte.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-sibyte.c 2006-03-22 17:06:16.000000000 +0100 -@@ -31,7 +31,7 @@ - { - .owner = THIS_MODULE, - .id = I2C_HW_SIBYTE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = NULL, - .algo_data = &sibyte_board_data[0], - .name = "SiByte SMBus 0", -@@ -39,7 +39,7 @@ - { - .owner = THIS_MODULE, - .id = I2C_HW_SIBYTE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = NULL, - .algo_data = &sibyte_board_data[1], - .name = "SiByte SMBus 1", ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis5595.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-sis5595.c 2006-03-22 17:06:16.000000000 +0100 -@@ -365,7 +365,7 @@ - - static struct i2c_adapter sis5595_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis630.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-sis630.c 2006-03-22 17:06:16.000000000 +0100 -@@ -457,7 +457,7 @@ - - static struct i2c_adapter sis630_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-stub.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-stub.c 2006-03-22 17:06:16.000000000 +0100 -@@ -115,7 +115,7 @@ - - static struct i2c_adapter stub_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_ALL, - .algo = &smbus_algorithm, - .name = "SMBus stub driver", - }; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-via.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-via.c 2006-03-22 17:06:16.000000000 +0100 -@@ -87,7 +87,7 @@ - - static struct i2c_adapter vt586b_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .name = "VIA i2c", - .algo_data = &bit_data, - }; ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-viapro.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-viapro.c 2006-03-22 17:06:16.000000000 +0100 -@@ -304,7 +304,7 @@ - - static struct i2c_adapter vt596_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_HWMON, -+ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, - .algo = &smbus_algorithm, - }; - ---- linux-2.6.16.orig/drivers/i2c/busses/i2c-voodoo3.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/i2c/busses/i2c-voodoo3.c 2006-03-22 17:06:16.000000000 +0100 -@@ -183,7 +183,7 @@ - - static struct i2c_adapter voodoo3_ddc_adapter = { - .owner = THIS_MODULE, -- .class = I2C_CLASS_DDC, -+ .class = I2C_CLASS_DATA, - .name = "DDC Voodoo3/Banshee adapter", - .algo_data = &voo_ddc_bit_data, - }; ---- linux-2.6.16.orig/drivers/video/aty/radeon_i2c.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/aty/radeon_i2c.c 2006-03-22 17:06:16.000000000 +0100 -@@ -75,6 +75,7 @@ - - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; -+ chan->adapter.class = I2C_CLASS_DATA; - chan->adapter.id = I2C_HW_B_RADEON; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->rinfo->pdev->dev; ---- linux-2.6.16.orig/drivers/video/i810/i810-i2c.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/i810/i810-i2c.c 2006-03-22 17:06:16.000000000 +0100 -@@ -85,12 +85,14 @@ - return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); - } - --static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) -+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, -+ unsigned long i2c_class) - { - int rc; - - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; -+ chan->adapter.class = i2c_class; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->par->dev->dev; - chan->adapter.id = I2C_HW_B_I810; -@@ -130,11 +132,11 @@ - par->chan[2].par = par; - - par->chan[0].ddc_base = GPIOA; -- i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); -+ i810_setup_i2c_bus(&par->chan[0], "I810-DDC", I2C_CLASS_DATA); - par->chan[1].ddc_base = GPIOB; -- i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); -+ i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 0); - par->chan[2].ddc_base = GPIOC; -- i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); -+ i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC", 0); - } - - void i810_delete_i2c_busses(struct i810fb_par *par) ---- linux-2.6.16.orig/drivers/video/matrox/i2c-matroxfb.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/matrox/i2c-matroxfb.c 2006-03-22 17:06:16.000000000 +0100 -@@ -104,13 +104,15 @@ - }; - - static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, -- unsigned int data, unsigned int clock, const char* name) { -+ unsigned int data, unsigned int clock, const char* name, -+ unsigned int i2c_class) { - int err; - - b->minfo = minfo; - b->mask.data = data; - b->mask.clock = clock; - b->adapter = matrox_i2c_adapter_template; -+ b->adapter.class = i2c_class; - snprintf(b->adapter.name, I2C_NAME_SIZE, name, - minfo->fbcon.node); - i2c_set_adapdata(&b->adapter, b); -@@ -160,22 +162,28 @@ - switch (ACCESS_FBINFO(chip)) { - case MGA_2064: - case MGA_2164: -- err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0"); -+ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, -+ DDC1B_CLK, "DDC:fb%u #0", -+ I2C_CLASS_DATA); - break; - default: -- err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0"); -+ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, -+ DDC1_CLK, "DDC:fb%u #0", -+ I2C_CLASS_DATA); - break; - } - if (err) - goto fail_ddc1; - if (ACCESS_FBINFO(devflags.dualhead)) { -- err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1"); -+ err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, -+ "DDC:fb%u #1", I2C_CLASS_DATA); - if (err == -ENODEV) { - printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n"); - } else if (err) - printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n"); - /* Register maven bus even on G450/G550 */ -- err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u"); -+ err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, -+ "MAVEN:fb%u", 0); - if (err) - printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); - } ---- linux-2.6.16.orig/drivers/video/nvidia/nv_i2c.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/nvidia/nv_i2c.c 2006-03-22 17:06:16.000000000 +0100 -@@ -96,6 +96,7 @@ - - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; -+ chan->adapter.class = I2C_CLASS_DATA; - chan->adapter.id = I2C_HW_B_NVIDIA; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->par->pci_dev->dev; ---- linux-2.6.16.orig/drivers/video/riva/rivafb-i2c.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/riva/rivafb-i2c.c 2006-03-22 17:06:16.000000000 +0100 -@@ -98,6 +98,7 @@ - - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; -+ chan->adapter.class = I2C_CLASS_DATA; - chan->adapter.id = I2C_HW_B_RIVA; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->par->pdev->dev; ---- linux-2.6.16.orig/drivers/video/savage/savagefb-i2c.c 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/video/savage/savagefb-i2c.c 2006-03-22 17:06:16.000000000 +0100 -@@ -145,6 +145,7 @@ - if (chan->par) { - strcpy(chan->adapter.name, name); - chan->adapter.owner = THIS_MODULE; -+ chan->adapter.class = I2C_CLASS_DATA; - chan->adapter.id = I2C_HW_B_SAVAGE; - chan->adapter.algo_data = &chan->algo; - chan->adapter.dev.parent = &chan->par->pcidev->dev; ---- linux-2.6.16.orig/drivers/media/video/zoran.h 2006-03-22 17:05:59.000000000 +0100 -+++ linux-2.6.16/drivers/media/video/zoran.h 2006-03-22 17:06:16.000000000 +0100 -@@ -355,6 +355,7 @@ - enum card_type type; - char name[32]; - u16 i2c_decoder, i2c_encoder; /* I2C types */ -+ u16 decoder_addr, encoder_addr; /* I2C chips address */ - u16 video_vfe, video_codec; /* videocodec types */ - u16 audio_chip; /* audio type */ - u16 vendor_id, device_id; /* subsystem vendor/device ID */ diff --git a/packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc6-ide1 b/packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc6-ide1 deleted file mode 100644 index f35facae1b..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc6-ide1 +++ /dev/null @@ -1,18684 +0,0 @@ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/arch/i386/pci/fixup.c linux-2.6.16-rc6/arch/i386/pci/fixup.c ---- linux.vanilla-2.6.16-rc6/arch/i386/pci/fixup.c 2006-03-13 14:00:11.000000000 +0000 -+++ linux-2.6.16-rc6/arch/i386/pci/fixup.c 2006-02-01 14:49:17.000000000 +0000 -@@ -74,52 +74,6 @@ - } - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); - --static void __devinit pci_fixup_ide_bases(struct pci_dev *d) --{ -- int i; -- -- /* -- * PCI IDE controllers use non-standard I/O port decoding, respect it. -- */ -- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) -- return; -- DBG("PCI: IDE base address fixup for %s\n", pci_name(d)); -- for(i=0; i<4; i++) { -- struct resource *r = &d->resource[i]; -- if ((r->start & ~0x80) == 0x374) { -- r->start |= 2; -- r->end = r->start; -- } -- } --} --DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); -- --static void __devinit pci_fixup_ide_trash(struct pci_dev *d) --{ -- int i; -- -- /* -- * Runs the fixup only for the first IDE controller -- * (Shai Fultheim - shai@ftcon.com) -- */ -- static int called = 0; -- if (called) -- return; -- called = 1; -- -- /* -- * There exist PCI IDE controllers which have utter garbage -- * in first four base registers. Ignore that. -- */ -- DBG("PCI: IDE base address trash cleared for %s\n", pci_name(d)); -- for(i=0; i<4; i++) -- d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; --} --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash); -- - static void __devinit pci_fixup_latency(struct pci_dev *d) - { - /* -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/cdrom/cdrom.c linux-2.6.16-rc6/drivers/cdrom/cdrom.c ---- linux.vanilla-2.6.16-rc6/drivers/cdrom/cdrom.c 2006-03-13 14:00:12.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/cdrom/cdrom.c 2006-01-17 16:34:19.000000000 +0000 -@@ -1131,7 +1131,8 @@ - This ensures that the drive gets unlocked after a mount fails. This - is a goto to avoid bloating the driver with redundant code. */ - clean_up_and_return: -- cdinfo(CD_OPEN, "open failed.\n"); -+ /* Don't log this, its a perfectly normal user occurence */ -+ /* cdinfo(CD_WARNING, "open failed.\n"); */ - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdo->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/pci/probe.c linux-2.6.16-rc6/drivers/pci/probe.c ---- linux.vanilla-2.6.16-rc6/drivers/pci/probe.c 2006-03-13 14:00:13.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/pci/probe.c 2006-02-01 15:56:28.000000000 +0000 -@@ -627,6 +627,7 @@ - static int pci_setup_device(struct pci_dev * dev) - { - u32 class; -+ u16 cmd; - - sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); -@@ -654,6 +655,31 @@ - pci_read_bases(dev, 6, PCI_ROM_ADDRESS); - pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); - pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); -+ -+ /* -+ * Do the ugly legacy mode stuff here rather than broken chip -+ * quirk code. Legacy mode ATA controllers have fixed -+ * addresses. These are not always echoed in BAR0-3, and -+ * BAR0-3 in a few cases contain junk! -+ */ -+ if (class == PCI_CLASS_STORAGE_IDE) { -+ u8 progif; -+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); -+ if ((progif & 5) != 5) { -+ dev->resource[0].start = 0x1F0; -+ dev->resource[0].end = 0x1F7; -+ dev->resource[0].flags = IORESOURCE_IO; -+ dev->resource[1].start = 0x3F6; -+ dev->resource[1].end = 0x3F6; -+ dev->resource[1].flags = IORESOURCE_IO; -+ dev->resource[2].start = 0x170; -+ dev->resource[2].end = 0x177; -+ dev->resource[2].flags = IORESOURCE_IO; -+ dev->resource[3].start = 0x376; -+ dev->resource[3].end = 0x376; -+ dev->resource[3].flags = IORESOURCE_IO; -+ } -+ } - break; - - case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/ata_generic.c linux-2.6.16-rc6/drivers/scsi/ata_generic.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/ata_generic.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/ata_generic.c 2006-02-16 15:35:41.000000000 +0000 -@@ -0,0 +1,241 @@ -+/* -+ * ata_generic.c - Generic PATA/SATA controller driver. -+ * Copyright 2005 Red Hat Inc <alan@redhat.com>, all rights reserved. -+ * -+ * Elements from ide/pci/generic.c -+ * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> -+ * Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com> -+ * -+ * May be copied or modified under the terms of the GNU General Public License -+ * -+ * Driver for PCI IDE interfaces implementing the standard bus mastering -+ * interface functionality. This assumes the BIOS did the drive set up and -+ * tuning for us. By default we do not grab all IDE class devices as they -+ * may have other drivers or need fixups to avoid problems. Instead we keep -+ * a default list of stuff without documentation/driver that appears to -+ * work. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include "scsi.h" -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "generic" -+#define DRV_VERSION "0.1" -+ -+/* -+ * A generic parallel ATA driver using libata -+ */ -+ -+static void genpata_phy_reset(struct ata_port *ap) -+{ -+ /* We know the BIOS already did the mode work. Don't tempt any -+ one else to "fix" things */ -+ ap->cbl = ATA_CBL_PATA80; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * genpata_set_mode - mode setting -+ * @ap: interface to set up -+ * -+ * Use a non standard set_mode function. We don't want to be tuned. -+ * The BIOS configured everything. Our job is not to fiddle. We -+ * read the dma enabled bits from the PCI configuration of the device -+ * and respect them. -+ */ -+ -+static void genpata_set_mode(struct ata_port *ap) -+{ -+ int dma_enabled; -+ int i; -+ -+ /* Bits 5 and 6 indicate if DMA is active on master/slave */ -+ dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ /* We don't really care */ -+ dev->pio_mode = XFER_PIO_0; -+ dev->dma_mode = XFER_MW_DMA_0; -+ /* We do need the right mode information for DMA or PIO -+ and this comes from the current configuration flags */ -+ /* FIXME: at some point in the future this should become -+ a library helper which reads the disk modes from the -+ disk as well */ -+ if (dma_enabled & (1 << (5 + i))) { -+ dev->xfer_mode = XFER_MW_DMA_0; -+ dev->xfer_shift = ATA_SHIFT_MWDMA; -+ dev->flags &= ~ATA_DFLAG_PIO; -+ } else { -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+ } -+} -+ -+static struct scsi_host_template genpata_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations genpata_port_ops = { -+ .set_mode = genpata_set_mode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = genpata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .data_xfer = ata_pio_data_xfer, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int ide_generic_all; /* Set to claim all devices */ -+ -+static int __init ide_generic_all_on(char *unused) -+{ -+ ide_generic_all = 1; -+ printk(KERN_INFO "ATA generic will claim all unknown PCI IDE class storage controllers.\n"); -+ return 1; -+} -+ -+__setup("all-generic-ide", ide_generic_all_on); -+ -+/** -+ * pata_generic_init - attach generic IDE -+ * @dev: PCI device found -+ * @id: match entry -+ * -+ * Called each time a matching IDE interface is found. We check if the -+ * interface is one we wish to claim and if so we perform any chip -+ * specific hacks then let the ATA layer do the heavy lifting. -+ */ -+ -+static int pata_generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ u16 command; -+ static struct ata_port_info info = { -+ .sht = &genpata_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_IRQ_MASK, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &genpata_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ /* Don't use the generic entry unless instructed to do so */ -+ if (id->driver_data == 1 && ide_generic_all == 0) -+ return -ENODEV; -+ -+ /* Devices that need care */ -+ if (dev->vendor == PCI_VENDOR_ID_UMC && -+ dev->device == PCI_DEVICE_ID_UMC_UM8886A && -+ (!(PCI_FUNC(dev->devfn) & 1))) -+ return -ENODEV; -+ -+ if (dev->vendor == PCI_VENDOR_ID_OPTI && -+ dev->device == PCI_DEVICE_ID_OPTI_82C558 && -+ (!(PCI_FUNC(dev->devfn) & 1))) -+ return -ENODEV; -+ -+ /* Don't re-enable devices in generic mode or we will break some -+ motherboards with disabled and unused IDE controllers */ -+ pci_read_config_word(dev, PCI_COMMAND, &command); -+ if (!(command & PCI_COMMAND_IO)) -+ return -ENODEV; -+ -+ if (dev->vendor == PCI_VENDOR_ID_AL) -+ ata_pci_clear_simplex(dev); -+ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id pata_generic[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, -+ /* Must come last. If you add entries adjust this table appropriately */ -+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, -+ { 0, }, -+}; -+ -+static struct pci_driver pata_generic_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pata_generic, -+ .probe = pata_generic_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init pata_generic_init(void) -+{ -+ return pci_module_init(&pata_generic_pci_driver); -+} -+ -+ -+static void __exit pata_generic_exit(void) -+{ -+ pci_unregister_driver(&pata_generic_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for generic ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, pata_generic); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(pata_generic_init); -+module_exit(pata_generic_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/ata_piix.c linux-2.6.16-rc6/drivers/scsi/ata_piix.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/ata_piix.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/ata_piix.c 2006-02-20 20:06:17.000000000 +0000 -@@ -91,9 +91,10 @@ - #include <linux/device.h> - #include <scsi/scsi_host.h> - #include <linux/libata.h> -+#include <linux/ata.h> - - #define DRV_NAME "ata_piix" --#define DRV_VERSION "1.05" -+#define DRV_VERSION "1.05-ac7" - - enum { - PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ -@@ -122,6 +123,17 @@ - piix4_pata = 2, - ich6_sata = 3, - ich6_sata_ahci = 4, -+ ich0_pata = 5, -+ ich2_pata = 6, -+ ich3_pata = 7, -+ ich4_pata = 8, -+ cich_pata = 9, -+ piix3_pata = 10, -+ esb_pata = 11, -+ ich_pata = 12, -+ ich6_pata = 13, -+ ich7_pata = 14, -+ esb2_pata = 15, - - PIIX_AHCI_DEVICE = 6, - }; -@@ -130,20 +142,69 @@ - const struct pci_device_id *ent); - - static void piix_pata_phy_reset(struct ata_port *ap); -+static void ich_pata_phy_reset(struct ata_port *ap); - static void piix_sata_phy_reset(struct ata_port *ap); - static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev); - static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); -+static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev); - - static unsigned int in_module_init = 1; - - static const struct pci_device_id piix_pci_tbl[] = { - #ifdef ATA_ENABLE_PATA -+#if 0 -+ /* Neptune and earlier are simple PIO */ -+ /* 430HX and friends. MWDMA */ -+ { 0x8086, 0x122e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+ { 0x8086, 0x1230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+ /* Intel PIIX3 */ -+ { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+#endif -+ /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ -+ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ - { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, - { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, - { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, -+ /* Intel PIIX4 */ -+ { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel PIIX4 */ -+ { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel PIIX */ -+ { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel ICH (i810, i815, i840) UDMA 66*/ -+ { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata }, -+ /* Intel ICH0 : UDMA 33*/ -+ { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich0_pata }, -+ /* Intel ICH2M */ -+ { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich2_pata }, -+ /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */ -+ { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich2_pata }, -+ /* Intel ICH3M */ -+ { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich3_pata }, -+ /* Intel ICH3 (E7500/1) UDMA 100 */ -+ { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich3_pata }, -+#if 0 -+ { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, dunno_pata }, -+#endif -+ /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ -+ { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich4_pata }, -+ { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich4_pata }, -+ /* Intel ICH5 */ -+ { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, -+ /* C-ICH (i810E2) */ -+ { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, cich_pata }, -+ /* ESB (855GME/875P + 6300ESB) UDMA 100 */ -+ { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_pata }, -+ /* ICH6 (and 6) (i915) UDMA 100 */ -+ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_pata }, -+ /* ICH7/7-R (i945, i975) UDMA 100*/ -+ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_pata }, -+ { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_pata }, - #endif -- -- /* NOTE: The following PCI ids must be kept in sync with the -+ /* -+ * SATA ports -+ * -+ * NOTE: The following PCI ids must be kept in sync with the - * list in drivers/pci/quirks.c. - */ - -@@ -213,6 +274,40 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations ich_pata_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = piix_set_piomode, -+ .set_dmamode = ich_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = ich_pata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ -+ .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - -@@ -242,6 +337,8 @@ - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - -+ .data_xfer = ata_pio_data_xfer, -+ - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, -@@ -253,47 +350,39 @@ - }; - - static struct ata_port_info piix_port_info[] = { -- /* ich5_pata */ -+ /* ich5_pata: 0*/ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | - PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ --#if 0 - .mwdma_mask = 0x06, /* mwdma1-2 */ --#else -- .mwdma_mask = 0x00, /* mwdma broken */ --#endif -- .udma_mask = 0x3f, /* udma0-5 */ -- .port_ops = &piix_pata_ops, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ich_pata_ops, - }, - -- /* ich5_sata */ -+ /* ich5_sata: 1 */ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | - PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ -- .udma_mask = 0x7f, /* udma0-6 */ -+ .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - -- /* piix4_pata */ -+ /* piix4_pata: 2 */ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ --#if 0 - .mwdma_mask = 0x06, /* mwdma1-2 */ --#else -- .mwdma_mask = 0x00, /* mwdma broken */ --#endif - .udma_mask = ATA_UDMA_MASK_40C, - .port_ops = &piix_pata_ops, - }, - -- /* ich6_sata */ -+ /* ich6_sata: 3 */ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | -@@ -301,11 +390,11 @@ - ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ -- .udma_mask = 0x7f, /* udma0-6 */ -+ .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, - -- /* ich6_sata_ahci */ -+ /* ich6_sata_ahci: 4 */ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | -@@ -313,9 +402,119 @@ - ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ -- .udma_mask = 0x7f, /* udma0-6 */ -+ .udma_mask = ATA_UDMA6, - .port_ops = &piix_sata_ops, - }, -+ -+ /* ich0_pata: 5 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = ATA_UDMA4, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich2_pata: 6 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich3_pata: 7 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich4_pata: 8 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* cich_pata: 9 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* piix3_pata: 10 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma1-2 */ -+ .udma_mask = ATA_UDMA_MASK_40C, -+ .port_ops = &piix_pata_ops, -+ }, -+ -+ /* esb_pata: 11 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &piix_pata_ops, -+ }, -+ -+ /* ich_pata: 12 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA4, /* UDMA66 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich6_pata: 13 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA6, /* UDMA133 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich7_pata: 14 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* esb2_pata: 15 */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &ich_pata_ops, -+ }, - }; - - static struct pci_bits piix_enable_bits[] = { -@@ -339,7 +538,7 @@ - * LOCKING: - * None (inherited from caller). - */ --static void piix_pata_cbl_detect(struct ata_port *ap) -+static void ich_pata_cbl_detect(struct ata_port *ap) - { - struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - u8 tmp, mask; -@@ -366,8 +565,9 @@ - * piix_pata_phy_reset - Probe specified port on PATA host controller - * @ap: Port to probe - * -- * Probe PATA phy. -- * -+ * Probe PATA phy. Unlike the ICH we have no IOCFG register and -+ * don't do UDMA66+ anyway. -+ - * LOCKING: - * None (inherited from caller). - */ -@@ -381,11 +581,34 @@ - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return; - } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} - -- piix_pata_cbl_detect(ap); - -- ata_port_probe(ap); -+/** -+ * ich_pata_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * Probe PATA phy. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void ich_pata_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - -+ if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ -+ ich_pata_cbl_detect(ap); -+ ata_port_probe(ap); - ata_bus_reset(ap); - } - -@@ -481,6 +704,13 @@ - unsigned int slave_port = 0x44; - u16 master_data; - u8 slave_data; -+ u8 udma_enable; -+ int control = 0; -+ -+ /* -+ * See Intel Document 298600-004 for the timing programing rules -+ * for ICH controllers. -+ */ - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, -@@ -489,20 +719,30 @@ - { 2, 1 }, - { 2, 3 }, }; - -+ if (pio > 2) -+ control |= 1; /* TIME1 enable */ -+ if (ata_pio_need_iordy(adev)) -+ control |= 2; /* IE enable */ -+ -+ /* Intel specifies that the PPE functionality is for disk only */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable */ -+ - pci_read_config_word(dev, master_port, &master_data); - if (is_slave) { -+ /* Enable SITRE (seperate slave timing register) */ - master_data |= 0x4000; -- /* enable PPE, IE and TIME */ -- master_data |= 0x0070; -+ /* enable PPE1, IE1 and TIME1 as needed */ -+ master_data |= (control << 4); - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= (ap->hard_port_no ? 0x0f : 0xf0); -- slave_data |= -- (timings[pio][0] << 2) | -- (timings[pio][1] << (ap->hard_port_no ? 4 : 0)); -+ /* Load the timing nibble for this slave */ -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->hard_port_no ? 4 : 0); - } else { -+ /* Master keeps the bits in a different format */ - master_data &= 0xccf8; -- /* enable PPE, IE and TIME */ -- master_data |= 0x0007; -+ /* Enable PPE, IE and TIME as appropriate */ -+ master_data |= control; - master_data |= - (timings[pio][0] << 12) | - (timings[pio][1] << 8); -@@ -510,84 +750,165 @@ - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); -+ -+ /* Ensure the UDMA bit is off - it will be turned back on if -+ UDMA is selected */ -+ -+ if (ap->udma_mask) { -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ udma_enable &= ~(1 << (2 * ap->hard_port_no + adev->devno)); -+ pci_write_config_byte(dev, 0x48, udma_enable); -+ } - } - - /** -- * piix_set_dmamode - Initialize host controller PATA PIO timings -+ * do_piix_set_dmamode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring -- * @adev: um -- * @udma: udma mode, 0 - 6 -+ * @adev: device to configure -+ * @isich: True if the device is an ICH and has IOCFG registers - * -- * Set UDMA mode for device, in host controller PCI config space. -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * Note: We know the caller has already set the PIO mode. In doing -+ * so it has correctly set PPE, SITRE, IORDY and TIME1. We rely on that. - * - * LOCKING: - * None (inherited from caller). - */ - --static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich) - { -- unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ - struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -- u8 maslave = ap->hard_port_no ? 0x42 : 0x40; -- u8 speed = udma; -- unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno; -- int a_speed = 3 << (drive_dn * 4); -- int u_flag = 1 << drive_dn; -- int v_flag = 0x01 << drive_dn; -- int w_flag = 0x10 << drive_dn; -- int u_speed = 0; -- int sitre; -- u16 reg4042, reg4a; -- u8 reg48, reg54, reg55; -- -- pci_read_config_word(dev, maslave, ®4042); -- DPRINTK("reg4042 = 0x%04x\n", reg4042); -- sitre = (reg4042 & 0x4000) ? 1 : 0; -- pci_read_config_byte(dev, 0x48, ®48); -- pci_read_config_word(dev, 0x4a, ®4a); -- pci_read_config_byte(dev, 0x54, ®54); -- pci_read_config_byte(dev, 0x55, ®55); -- -- switch(speed) { -- case XFER_UDMA_4: -- case XFER_UDMA_2: u_speed = 2 << (drive_dn * 4); break; -- case XFER_UDMA_6: -- case XFER_UDMA_5: -- case XFER_UDMA_3: -- case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break; -- case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break; -- case XFER_MW_DMA_2: -- case XFER_MW_DMA_1: break; -- default: -- BUG(); -- return; -- } -+ u8 master_port = ap->hard_port_no ? 0x42 : 0x40; -+ u16 master_data; -+ u8 speed = adev->dma_mode; -+ int devid = adev->devno + 2 * ap->hard_port_no; -+ u8 udma_enable; -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; - -+ pci_read_config_word(dev, master_port, &master_data); -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ - if (speed >= XFER_UDMA_0) { -- if (!(reg48 & u_flag)) -- pci_write_config_byte(dev, 0x48, reg48 | u_flag); -- if (speed == XFER_UDMA_5) { -- pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); -- } else { -- pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); -+ unsigned int udma = adev->dma_mode - XFER_UDMA_0; -+ u16 udma_timing; -+ u16 ideconf; -+ int u_clock, u_speed; -+ -+ /* -+ * UDMA is handled by a combination of clock switching and -+ * selection of dividers -+ * -+ * Handy rule: Odd modes are UDMATIMx 01, even are 02 -+ * except UDMA0 which is 00 -+ */ -+ u_speed = min(2 - (udma & 1), udma); -+ if (udma == 5) -+ u_clock = 0x1000; /* 100Mhz */ -+ else if (udma > 2) -+ u_clock = 1; /* 66Mhz */ -+ else -+ u_clock = 0; /* 33Mhz */ -+ -+ udma_enable |= (1 << devid); -+ -+ /* Load the CT/RP selection */ -+ pci_read_config_word(dev, 0x4A, &udma_timing); -+ udma_timing &= ~(3 << (4 * devid)); -+ udma_timing |= u_speed << (4 * devid); -+ pci_write_config_word(dev, 0x4A, udma_timing); -+ -+ if (isich) { -+ /* Select a 33/66/100Mhz clock */ -+ pci_read_config_word(dev, 0x54, &ideconf); -+ ideconf &= ~(0x1001 << devid); -+ ideconf |= u_clock << devid; -+ /* For ICH or later we should set bit 10 for better -+ performance (WR_PingPong_En) */ -+ pci_write_config_word(dev, 0x54, ideconf); - } -- if ((reg4a & a_speed) != u_speed) -- pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); -- if (speed > XFER_UDMA_2) { -- if (!(reg54 & v_flag)) -- pci_write_config_byte(dev, 0x54, reg54 | v_flag); -- } else -- pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else { -- if (reg48 & u_flag) -- pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); -- if (reg4a & a_speed) -- pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); -- if (reg54 & v_flag) -- pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); -- if (reg55 & w_flag) -- pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); -+ /* -+ * MWDMA is driven by the PIO timings. We must also enable -+ * IORDY unconditionally along with TIME1. PPE has already -+ * been set when the PIO timing was set. -+ */ -+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; -+ unsigned int control; -+ u8 slave_data; -+ const unsigned int needed_pio[3] = { -+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 -+ }; -+ int pio = needed_pio[mwdma] - XFER_PIO_0; -+ -+ control = 3; /* IORDY|TIME1 */ -+ -+ /* If the drive MWDMA is faster than it can do PIO then -+ we must force PIO into PIO0 */ -+ -+ if (adev->pio_mode < needed_pio[mwdma]) -+ /* Enable DMA timing only */ -+ control |= 8; /* PIO cycles in PIO0 */ -+ -+ if (adev->devno) { /* Slave */ -+ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ -+ master_data |= control << 4; -+ pci_read_config_byte(dev, 0x44, &slave_data); -+ slave_data &= (0x0F + 0xE1 * ap->hard_port_no); -+ /* Load the matching timing */ -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->hard_port_no ? 4 : 0); -+ pci_write_config_byte(dev, 0x44, slave_data); -+ } else { /* Master */ -+ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY -+ and master timing bits */ -+ master_data |= control; -+ master_data |= -+ (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ } -+ udma_enable &= ~(1 << devid); -+ pci_write_config_word(dev, master_port, master_data); - } -+ /* Don't scribble on 0x48 if the controller does not support UDMA */ -+ if (ap->udma_mask) -+ pci_write_config_byte(dev, 0x48, udma_enable); -+} -+ -+/** -+ * piix_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ do_pata_set_dmamode(ap, adev, 0); -+} -+ -+/** -+ * ich_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ do_pata_set_dmamode(ap, adev, 1); - } - - #define AHCI_PCI_BAR 5 -@@ -646,15 +967,15 @@ - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - pci_read_config_word(pdev, 0x41, &cfg); - /* Only on the original revision: IDE DMA can hang */ -- if(rev == 0x00) -+ if (rev == 0x00) - no_piix_dma = 1; - /* On all revisions below 5 PXB bus lock must be disabled for IDE */ -- else if(cfg & (1<<14) && rev < 5) -+ else if (cfg & (1<<14) && rev < 5) - no_piix_dma = 2; - } -- if(no_piix_dma) -+ if (no_piix_dma) - dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); -- if(no_piix_dma == 2) -+ if (no_piix_dma == 2) - dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); - return no_piix_dma; - } -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/Kconfig linux-2.6.16-rc6/drivers/scsi/Kconfig ---- linux.vanilla-2.6.16-rc6/drivers/scsi/Kconfig 2006-03-13 14:00:13.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/Kconfig 2006-02-20 17:27:24.000000000 +0000 -@@ -599,6 +599,316 @@ - depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX) - default y - -+config SCSI_PATA_ALI -+ tristate "ALi PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ALi ATA interfaces -+ found on the many ALi chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_AMD -+ tristate "AMD/NVidia PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the AMD and NVidia PATA -+ interfaces found on the chipsets for Athlon/Athlon64. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ARTOP -+ tristate "ARTOP 6210/6260 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for ARTOP PATA controllers. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ATIIXP -+ tristate "ATI PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the ATI ATA interfaces -+ found on the many ATI chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CMD64X -+ tristate "CMD64x PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the CMD64x series chips -+ except for the CMD640. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5520 -+ tristate "CS5510/5520 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the Cyrix 5510/5520 -+ companion chip used with the MediaGX/Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5530 -+ tristate "CS5530 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Cyrix/NatSemi/AMD CS5530 -+ companion chip used with the MediaGX/Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5535 -+ tristate "CS5535 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && X86 && !X86_64 && EXPERIMENTAL -+ help -+ This option enables support for the NatSemi/AMD CS5535 -+ companion chip used with the Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CYPRESS -+ tristate "Cypress CY82C693 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Cypress/Contaq CY82C693 -+ chipset found in some Alpha systems -+ -+ If unsure, say N. -+ -+config SCSI_PATA_EFAR -+ tristate "EFAR SLC90E66 support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the EFAR SLC90E66 -+ IDE controller found on some older machines. -+ -+ If unsure, say N. -+ -+config SCSI_ATA_GENERIC -+ tristate "Generic PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for generic BIOS configured -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT37X -+ tristate "HPT 370/370A/371/372/374/302 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the majority of the later HPT -+ PATA controllers via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT3X2N -+ tristate "HPT 372N/302N PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the N variant HPT PATA -+ controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT3X3 -+ tristate "HPT 343/363 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the HPT 343/363 -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ISAPNP -+ tristate "ISA Plug and Play PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && EXPERIMENTAL -+ help -+ This option enables support for ISA plug & play ATA -+ controllers such as those found on old soundcards. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_IT8172 -+ tristate "IT8172 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ITE 8172 PATA controller -+ via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_IT821X -+ tristate "IT821x PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ITE 8211 and 8212 -+ PATA controllers via the new ATA layer, including RAID -+ mode. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_LEGACY -+ tristate "Legacy ISA PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for ISA bus legacy PATA -+ interfaces on ide2-5 and allows them to be accessed via -+ the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_MPIIX -+ tristate "Intel PATA MPIIX support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for MPIIX PATA support. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_NETCELL -+ tristate "NETCELL Revolution RAID support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the Netcell Revolution RAID -+ PATA controller. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_NS87410 -+ tristate "Nat Semi NS87410 PATA support (Experimental)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the National Semiconductor -+ NS87410 PCI-IDE controller. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_OLDPIIX -+ tristate "Intel PATA old PIIX support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for early PIIX PATA interfaces. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_OPTI -+ tristate "OPTI621/6215 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables full PIO support for the early Opti ATA -+ controllers found on some old motherboards. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_PCMCIA -+ tristate "PCMCIA PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCMCIA -+ help -+ This option enables support for PCMCIA ATA interfaces, including -+ compact flash card adapters via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_PDC_OLD -+ tristate "Older Promise PATA controller support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Promise 20246, 20262, 20263, -+ 20265 and 20267 adapters. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_QDI -+ tristate "QDI VLB PATA support" -+ depends on SCSI_SATA -+ help -+ Support for QDI 6500 and 6580 PATA controllers on VESA local bus. -+ -+config SCSI_PATA_RADISYS -+ tristate "RADISYS 82600 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the RADISYS 82600 -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_RZ1000 -+ tristate "PC Tech RZ1000 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables basic support for the PC Tech RZ1000/1 -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SC1200 -+ tristate "SC1200 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the NatSemi/AMD SC1200 SoC -+ companion chip used with the Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SERVERWORKS -+ tristate "SERVERWORKS OSB4/CSB5/CSB6 PATA support (Experimental)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Serverworks OSB4/CSB5 and -+ CSB6 IDE controllers, via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SIL680 -+ tristate "CMD / Silicon Image 680 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for CMD / Silicon Image 680 PATA. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SIS -+ tristate "SiS PATA support (Experimental)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for SiS PATA controllers -+ -+ If unsure, say N. -+ -+config SCSI_PATA_TRIFLEX -+ tristate "Compaq Triflex PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ Enable support for the Compaq 'Triflex' IDE controller as found -+ on many Compaq Pentium-Pro systems, via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_VIA -+ tristate "VIA PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the VIA PATA interfaces -+ found on the many VIA chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_WINBOND -+ tristate "Winbond SL82C105 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for SL82C105 PATA devices found in the -+ Netwinder and some other systems -+ -+ If unsure, say N. -+ -+ - config SCSI_BUSLOGIC - tristate "BusLogic SCSI support" - depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/libata-core.c linux-2.6.16-rc6/drivers/scsi/libata-core.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/libata-core.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/libata-core.c 2006-03-13 14:30:45.838552760 +0000 -@@ -68,9 +68,10 @@ - static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); - static void ata_set_mode(struct ata_port *ap); - static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); --static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift); -+static unsigned int ata_get_mode_mask(const struct ata_port *ap, struct ata_device *adev, int shift); - static int fgb(u32 bitmap); - static int ata_choose_xfer_mode(const struct ata_port *ap, -+ struct ata_device *adev, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out); - static void __ata_qc_complete(struct ata_queued_cmd *qc); -@@ -78,7 +79,7 @@ - static unsigned int ata_unique_id = 1; - static struct workqueue_struct *ata_wq; - --int atapi_enabled = 0; -+int atapi_enabled = 1; - module_param(atapi_enabled, int, 0444); - MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); - -@@ -1209,6 +1210,48 @@ - return 0; - } - -+static void ata_dev_check_hpa(struct ata_port *ap, struct ata_device *dev) -+{ -+ struct ata_taskfile tf; -+ unsigned long long true_size; -+ unsigned int err_mask; -+ -+ if (!ata_id_has_hpa(dev->id) || !ata_id_hpa_enabled(dev->id)) -+ return; -+ -+ /* Issue a query for HPA */ -+ ata_dev_select(ap, dev->devno, 1, 1); -+ ata_tf_init(ap, &tf, dev->devno); -+ -+ if (dev->flags & ATA_DFLAG_LBA48) { -+ tf.command = ATA_CMD_READ_NATIVE_MAX_EXT; -+ tf.device |= 0x40; -+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); -+ if (err_mask) -+ return; -+ /* Ok HPA is live */ -+ true_size = (tf.hob_lbah << 16) | (tf.hob_lbam << 8) | (tf.hob_lbal); -+ true_size <<= 24; -+ true_size |= (tf.lbah << 16) | (tf.lbam << 8) | tf.lbal; -+ } else { -+ tf.command = ATA_CMD_READ_NATIVE_MAX; -+ tf.device |= 0x40; -+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); -+ if (err_mask) -+ return; -+ /* Ok HPA is live */ -+ true_size = ((tf.device & 0x0F) << 24) | -+ (tf.lbah << 16) | -+ (tf.lbam << 8) | -+ tf.lbal; -+ } -+ dev->flags |= ATA_DFLAG_HPA; -+ /* Should save the HPA value and expose it for dmraid then -+ remove the clipping */ -+ printk(KERN_INFO "HPA present: true size %lld sectors.\n", -+ true_size + 1); -+} -+ - /** - * ata_dev_identify - obtain IDENTIFY x DEVICE page - * @ap: port on which device we wish to probe resides -@@ -1332,7 +1375,7 @@ - - /* ATA-specific feature tests */ - if (dev->class == ATA_DEV_ATA) { -- if (!ata_id_is_ata(dev->id)) /* sanity check */ -+ if (!ata_id_is_ata(dev->id) && !ata_id_is_cfa(dev->id)) /* sanity check */ - goto err_out_nosup; - - /* get major version */ -@@ -1404,6 +1447,13 @@ - } - - ap->host->max_cmd_len = 16; -+ -+ /* -+ * See if we have the HPA misfeature on the drive -+ */ -+#if 0 /* TESTING */ -+ ata_dev_check_hpa(ap, dev); -+#endif - } - - /* ATAPI-specific feature tests */ -@@ -1489,10 +1539,24 @@ - ap->ops->phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out; -+ -+ /* The reset means we are in PIO 0, but the controller may not -+ yet be correctly set up and may have old BIOS settings, or just -+ no settings at all. Set all the devices to PIO 0 */ -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) -+ ap->device[i].pio_mode = XFER_PIO_0; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *adev = & ap->device[i]; -+ -+ /* Set up the controller on this port for PIO 0. We must not -+ send the drive speed setting commands at this point */ -+ if (ap->ops->set_piomode) -+ ap->ops->set_piomode(ap, adev); -+ - ata_dev_identify(ap, i); -- if (ata_dev_present(&ap->device[i])) { -+ if (ata_dev_present(adev)) { - found = 1; - ata_dev_config(ap,i); - } -@@ -1501,7 +1565,11 @@ - if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - goto err_out_disable; - -- ata_set_mode(ap); -+ if(ap->ops->set_mode) -+ ap->ops->set_mode(ap); -+ else -+ ata_set_mode(ap); -+ - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out_disable; - -@@ -1616,6 +1684,23 @@ - } - - /** -+ * ata_dev_pair - return other device on cable -+ * @ap: port -+ * @adev: device -+ * -+ * Obtain the other device on the same cable, or if none is -+ * present NULL is returned -+ */ -+ -+struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct ata_device *pair = &ap->device[1 - adev->devno]; -+ if (!ata_dev_present(pair)) -+ return NULL; -+ return pair; -+} -+ -+/** - * ata_port_disable - Disable port. - * @ap: Port to be disabled. - * -@@ -1828,16 +1913,19 @@ - ap->id, dev->devno, xfer_mode_str[idx]); - } - --static int ata_host_set_pio(struct ata_port *ap) -+static int ata_host_set_pio(struct ata_port *ap, struct ata_device *adev) - { - unsigned int mask; -- int x, i; -+ int x; - u8 base, xfer_mode; - -- mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); -+ if (!ata_dev_present(adev)) -+ return 0; -+ -+ mask = ata_get_mode_mask(ap, adev, ATA_SHIFT_PIO); - x = fgb(mask); - if (x < 0) { -- printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); -+ printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, adev->devno); - return -1; - } - -@@ -1847,34 +1935,24 @@ - DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", - (int)base, (int)xfer_mode, mask, x); - -- for (i = 0; i < ATA_MAX_DEVICES; i++) { -- struct ata_device *dev = &ap->device[i]; -- if (ata_dev_present(dev)) { -- dev->pio_mode = xfer_mode; -- dev->xfer_mode = xfer_mode; -- dev->xfer_shift = ATA_SHIFT_PIO; -- if (ap->ops->set_piomode) -- ap->ops->set_piomode(ap, dev); -- } -- } -+ adev->pio_mode = xfer_mode; -+ adev->xfer_mode = xfer_mode; -+ adev->xfer_shift = ATA_SHIFT_PIO; -+ if (ap->ops->set_piomode) -+ ap->ops->set_piomode(ap, adev); - - return 0; - } - --static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, -- unsigned int xfer_shift) -+static void ata_host_set_dma(struct ata_port *ap, struct ata_device *adev, -+ u8 xfer_mode, unsigned int xfer_shift) - { -- int i; -- -- for (i = 0; i < ATA_MAX_DEVICES; i++) { -- struct ata_device *dev = &ap->device[i]; -- if (ata_dev_present(dev)) { -- dev->dma_mode = xfer_mode; -- dev->xfer_mode = xfer_mode; -- dev->xfer_shift = xfer_shift; -- if (ap->ops->set_dmamode) -- ap->ops->set_dmamode(ap, dev); -- } -+ if (ata_dev_present(adev)) { -+ adev->dma_mode = xfer_mode; -+ adev->xfer_mode = xfer_mode; -+ adev->xfer_shift = xfer_shift; -+ if (ap->ops->set_dmamode) -+ ap->ops->set_dmamode(ap, adev); - } - } - -@@ -1890,32 +1968,64 @@ - */ - static void ata_set_mode(struct ata_port *ap) - { -- unsigned int xfer_shift; -- u8 xfer_mode; -+ unsigned int xfer_shift[ATA_MAX_DEVICES]; -+ u8 xfer_mode[ATA_MAX_DEVICES]; - int rc; -+ int i; -+ int used_dma = 0; /* Track if DMA was used for this setup */ - -- /* step 1: always set host PIO timings */ -- rc = ata_host_set_pio(ap); -- if (rc) -- goto err_out; -+ /* We need to set timings individually for each device */ - -- /* step 2: choose the best data xfer mode */ -- xfer_mode = xfer_shift = 0; -- rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); -- if (rc) -- goto err_out; -+ /* Compute the timings first so that when we ask the device to do -+ speed configuration it can see all the intended device state in -+ full */ -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *adev = &ap->device[i]; -+ /* Choose the best data xfer mode */ -+ xfer_mode[i] = xfer_shift[i] = 0; -+ rc = ata_choose_xfer_mode(ap, adev, &xfer_mode[i], &xfer_shift[i]); -+ if (rc) -+ goto err_out; - -- /* step 3: if that xfer mode isn't PIO, set host DMA timings */ -- if (xfer_shift != ATA_SHIFT_PIO) -- ata_host_set_dma(ap, xfer_mode, xfer_shift); -- -- /* step 4: update devices' xfer mode */ -- ata_dev_set_mode(ap, &ap->device[0]); -- ata_dev_set_mode(ap, &ap->device[1]); -+ } -+ -+ /* Now set the mode tables we have computed */ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *adev = &ap->device[i]; -+ /* step 1: always set host PIO timings */ -+ rc = ata_host_set_pio(ap, adev); -+ if (rc) -+ goto err_out; -+ -+ /* step 2: if that xfer mode isn't PIO, set host DMA timings */ -+ if (xfer_shift[i] != ATA_SHIFT_PIO) { -+ ata_host_set_dma(ap, adev, xfer_mode[i], xfer_shift[i]); -+ used_dma = 1; -+ } -+ -+ /* In some cases the DMA mode will cause the driver to -+ update the pio mode to match chip limits. */ -+ -+ /* step 3: update devices' xfer mode */ -+ ata_dev_set_mode(ap, adev); -+ } - - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; - -+ /* -+ * Record simplex status. If we selected DMA then the other -+ * host channels are not permitted to do so. -+ */ -+ -+ if (used_dma && (ap->host_set->host_set_flags & ATA_HOST_SIMPLEX)) -+ ap->host_set->simplex_claimed = 1; -+ -+ /* -+ * Chip specific finalisation -+ */ -+ - if (ap->ops->post_set_mode) - ap->ops->post_set_mode(ap); - -@@ -2054,6 +2164,12 @@ - * crazy ATAPI devices... - */ - msleep(150); -+ /* Before we perform post reset processing we want to see if -+ the bus shows 0xFF because the odd clown forgets the D7 pulldown -+ resistor */ -+ -+ if (ata_check_status(ap) == 0xFF) -+ return 1; /* Positive is failure for some reason */ - - return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); - } -@@ -2087,9 +2203,17 @@ - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. -+ * -+ * Old drivers/ide uses the 2mS rule and then waits for ready - */ - msleep(150); -- -+ -+ /* Before we perform post reset processing we want to see if -+ the bus shows 0xFF because the odd clown forgets the D7 pulldown -+ resistor */ -+ -+ if (ata_check_status(ap) == 0xFF) -+ return 1; /* Positive is failure for some reason */ - ata_bus_post_reset(ap, devmask); - - return 0; -@@ -2204,132 +2328,126 @@ - } - - static const char * const ata_dma_blacklist [] = { -- "WDC AC11000H", -- "WDC AC22100H", -- "WDC AC32500H", -- "WDC AC33100H", -- "WDC AC31600H", -- "WDC AC32100H", -- "WDC AC23200L", -- "Compaq CRD-8241B", -- "CRD-8400B", -- "CRD-8480B", -- "CRD-8482B", -- "CRD-84", -- "SanDisk SDP3B", -- "SanDisk SDP3B-64", -- "SANYO CD-ROM CRD", -- "HITACHI CDR-8", -- "HITACHI CDR-8335", -- "HITACHI CDR-8435", -- "Toshiba CD-ROM XM-6202B", -- "TOSHIBA CD-ROM XM-1702BC", -- "CD-532E-A", -- "E-IDE CD-ROM CR-840", -- "CD-ROM Drive/F5A", -- "WPI CDD-820", -- "SAMSUNG CD-ROM SC-148C", -- "SAMSUNG CD-ROM SC", -- "SanDisk SDP3B-64", -- "ATAPI CD-ROM DRIVE 40X MAXIMUM", -- "_NEC DV5800A", -+ "WDC AC11000H", NULL, -+ "WDC AC22100H", NULL, -+ "WDC AC32500H", NULL, -+ "WDC AC33100H", NULL, -+ "WDC AC31600H", NULL, -+ "WDC AC32100H", "24.09P07", -+ "WDC AC23200L", "21.10N21", -+ "Compaq CRD-8241B", NULL, -+ "CRD-8400B", NULL, -+ "CRD-8480B", NULL, -+ "CRD-8482B", NULL, -+ "CRD-84", NULL, -+ "SanDisk SDP3B", NULL, -+ "SanDisk SDP3B-64", NULL, -+ "SANYO CD-ROM CRD", NULL, -+ "HITACHI CDR-8", NULL, -+ "HITACHI CDR-8335", NULL, -+ "HITACHI CDR-8435", NULL, -+ "Toshiba CD-ROM XM-6202B", NULL, -+ "TOSHIBA CD-ROM XM-1702BC", NULL, -+ "CD-532E-A", NULL, -+ "E-IDE CD-ROM CR-840", NULL, -+ "CD-ROM Drive/F5A", NULL, -+ "WPI CDD-820", NULL, -+ "SAMSUNG CD-ROM SC-148C", NULL, -+ "SAMSUNG CD-ROM SC", NULL, -+ "SanDisk SDP3B-64", NULL, -+ "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, -+ "_NEC DV5800A", NULL, -+ "SAMSUNG CD-ROM SN-124", "N001" - }; - --static int ata_dma_blacklisted(const struct ata_device *dev) -+static int ata_strim(char *s, size_t len) - { -- unsigned char model_num[40]; -- char *s; -- unsigned int len; -- int i; -- -- ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, -- sizeof(model_num)); -- s = &model_num[0]; -- len = strnlen(s, sizeof(model_num)); -+ len = strnlen(s, len); - - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } -+ return len; -+} - -- for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) -- if (!strncmp(ata_dma_blacklist[i], s, len)) -- return 1; -+static int ata_dma_blacklisted(const struct ata_device *dev) -+{ -+ unsigned char model_num[40]; -+ unsigned char model_rev[16]; -+ unsigned int nlen, rlen; -+ int i; - -+ ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, -+ sizeof(model_num)); -+ ata_dev_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, -+ sizeof(model_rev)); -+ nlen = ata_strim(model_num, sizeof(model_num)); -+ rlen = ata_strim(model_rev, sizeof(model_rev)); -+ -+ for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { -+ if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { -+ if (ata_dma_blacklist[i+1] == NULL) -+ return 1; -+ if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) -+ return 1; -+ } -+ } - return 0; - } - --static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) -+static unsigned int ata_get_mode_mask(const struct ata_port *ap, struct ata_device *adev, int shift) - { -- const struct ata_device *master, *slave; - unsigned int mask; -+ struct ata_host_set *hs = ap->host_set; -+ -+ if (!ata_dev_present(adev)) -+ return 0xFF; /* Drive isn't limiting anything */ -+ -+ if (shift == ATA_SHIFT_PIO) { -+ u16 tmp_mode = ata_pio_modes(adev); -+ mask = ap->pio_mask; -+ mask &= tmp_mode; -+ } - -- master = &ap->device[0]; -- slave = &ap->device[1]; -+ /* -+ * Enforce simplex rules if host is simplex -+ */ - -- assert (ata_dev_present(master) || ata_dev_present(slave)); -+ if (hs->host_set_flags & ATA_HOST_SIMPLEX) { -+ if (hs->simplex_claimed) { -+ if (shift != ATA_SHIFT_PIO) -+ return 0; -+ } -+ } - - if (shift == ATA_SHIFT_UDMA) { - mask = ap->udma_mask; -- if (ata_dev_present(master)) { -- mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); -- if (ata_dma_blacklisted(master)) { -- mask = 0; -- ata_pr_blacklisted(ap, master); -- } -- } -- if (ata_dev_present(slave)) { -- mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); -- if (ata_dma_blacklisted(slave)) { -- mask = 0; -- ata_pr_blacklisted(ap, slave); -- } -+ mask &= (adev->id[ATA_ID_UDMA_MODES] & 0xff); -+ if (ata_dma_blacklisted(adev)) { -+ mask = 0; -+ ata_pr_blacklisted(ap, adev); - } -+ /* 40 pin cable enforcement */ -+ if (ap->cbl == ATA_CBL_PATA40) -+ mask &= ATA_UDMA_MASK_40C; - } - else if (shift == ATA_SHIFT_MWDMA) { - mask = ap->mwdma_mask; -- if (ata_dev_present(master)) { -- mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); -- if (ata_dma_blacklisted(master)) { -- mask = 0; -- ata_pr_blacklisted(ap, master); -- } -- } -- if (ata_dev_present(slave)) { -- mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); -- if (ata_dma_blacklisted(slave)) { -- mask = 0; -- ata_pr_blacklisted(ap, slave); -- } -- } -- } -- else if (shift == ATA_SHIFT_PIO) { -- mask = ap->pio_mask; -- if (ata_dev_present(master)) { -- /* spec doesn't return explicit support for -- * PIO0-2, so we fake it -- */ -- u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; -- tmp_mode <<= 3; -- tmp_mode |= 0x7; -- mask &= tmp_mode; -- } -- if (ata_dev_present(slave)) { -- /* spec doesn't return explicit support for -- * PIO0-2, so we fake it -- */ -- u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; -- tmp_mode <<= 3; -- tmp_mode |= 0x7; -- mask &= tmp_mode; -+ mask &= (adev->id[ATA_ID_MWDMA_MODES] & 0x07); -+ if (ata_dma_blacklisted(adev)) { -+ mask = 0; -+ ata_pr_blacklisted(ap, adev); - } -- } -- else { -- mask = 0xffffffff; /* shut up compiler warning */ -- BUG(); -- } -- -+ } else if (shift != ATA_SHIFT_PIO) -+ panic("gmm:bad shift"); /* BUG confuses the compiler */ -+ /* -+ * Allow the controller to see the proposed mode and -+ * device data to do any custom filtering rules. -+ */ -+ if(ap->ops->mode_filter) -+ mask = ap->ops->mode_filter(ap, adev, mask, shift); - return mask; - } - -@@ -2349,6 +2467,7 @@ - /** - * ata_choose_xfer_mode - attempt to find best transfer mode - * @ap: Port for which an xfer mode will be selected -+ * @adev: ATA device for which xfer mode is being selected - * @xfer_mode_out: (output) SET FEATURES - XFER MODE code - * @xfer_shift_out: (output) bit shift that selects this mode - * -@@ -2363,6 +2482,7 @@ - */ - - static int ata_choose_xfer_mode(const struct ata_port *ap, -+ struct ata_device *adev, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out) - { -@@ -2371,7 +2491,7 @@ - - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { - shift = xfer_mode_classes[i].shift; -- mask = ata_get_mode_mask(ap, shift); -+ mask = ata_get_mode_mask(ap, adev, shift); - - x = fgb(mask); - if (x >= 0) { -@@ -3007,6 +3127,7 @@ - /** - * ata_mmio_data_xfer - Transfer data by MMIO - * @ap: port to read/write -+ * @adev: device to target - * @buf: data buffer - * @buflen: buffer length - * @write_data: read/write -@@ -3017,8 +3138,8 @@ - * Inherited from caller. - */ - --static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, -- unsigned int buflen, int write_data) -+void ata_mmio_data_xfer(struct ata_port *ap, struct ata_device *adev, -+ unsigned char *buf, unsigned int buflen, int write_data) - { - unsigned int i; - unsigned int words = buflen >> 1; -@@ -3052,6 +3173,7 @@ - /** - * ata_pio_data_xfer - Transfer data by PIO - * @ap: port to read/write -+ * @adev: device to target - * @buf: data buffer - * @buflen: buffer length - * @write_data: read/write -@@ -3062,11 +3184,11 @@ - * Inherited from caller. - */ - --static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, -- unsigned int buflen, int write_data) -+void ata_pio_data_xfer(struct ata_port *ap, struct ata_device *adev, -+ unsigned char *buf, unsigned int buflen, int write_data) - { - unsigned int words = buflen >> 1; -- -+ - /* Transfer multiple of 2 bytes */ - if (write_data) - outsw(ap->ioaddr.data_addr, buf, words); -@@ -3089,36 +3211,55 @@ - } - - /** -- * ata_data_xfer - Transfer data from/to the data register. -+ * ata_pio_data_xfer_noirq - Transfer data from/to the data register. - * @ap: port to read/write -+ * @adev: device to target - * @buf: data buffer - * @buflen: buffer length - * @do_write: read/write - * -- * Transfer data from/to the device data register. -+ * Transfer data from/to the device data register. This variant -+ * ensures local IRQs do not interrupt the data stream and this -+ * is needed for some controllers. - * - * LOCKING: - * Inherited from caller. - */ - --static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, -- unsigned int buflen, int do_write) -+void ata_pio_data_xfer_noirq(struct ata_port *ap, struct ata_device *adev, -+ unsigned char *buf, unsigned int buflen, int do_write) - { - /* Make the crap hardware pay the costs not the good stuff */ -- if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) { -- unsigned long flags; -- local_irq_save(flags); -- if (ap->flags & ATA_FLAG_MMIO) -- ata_mmio_data_xfer(ap, buf, buflen, do_write); -- else -- ata_pio_data_xfer(ap, buf, buflen, do_write); -- local_irq_restore(flags); -- } else { -- if (ap->flags & ATA_FLAG_MMIO) -- ata_mmio_data_xfer(ap, buf, buflen, do_write); -- else -- ata_pio_data_xfer(ap, buf, buflen, do_write); -- } -+ unsigned long flags; -+ local_irq_save(flags); -+ ata_pio_data_xfer(ap, adev, buf, buflen, do_write); -+ local_irq_restore(flags); -+} -+ -+/** -+ * ata_mmio_data_xfer_noirq - Transfer data from/to the data register. -+ * @ap: address to read/write -+ * @adev: device to target -+ * @buf: data buffer -+ * @buflen: buffer length -+ * @do_write: read/write -+ * -+ * Transfer data from/to the device data register. This variant -+ * ensures local IRQs do not interrupt the data stream and this -+ * is needed for some controllers. -+ * -+ * LOCKING: -+ * Inherited from caller. -+ */ -+ -+void ata_mmio_data_xfer_noirq(struct ata_port *ap, struct ata_device *adev, -+ unsigned char *buf, unsigned int buflen, int do_write) -+{ -+ /* Make the crap hardware pay the costs not the good stuff */ -+ unsigned long flags; -+ local_irq_save(flags); -+ ata_mmio_data_xfer(ap, adev, buf, buflen, do_write); -+ local_irq_restore(flags); - } - - /** -@@ -3164,7 +3305,7 @@ - - /* do the actual data transfer */ - do_write = (qc->tf.flags & ATA_TFLAG_WRITE); -- ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); -+ ap->ops->data_xfer(ap, qc->dev, buf, ATA_SECT_SIZE, do_write); - - kunmap(page); - } -@@ -3211,7 +3352,7 @@ - ap->id, bytes); - - for (i = 0; i < words; i++) -- ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); -+ ap->ops->data_xfer(ap, qc->dev, (unsigned char*)pad_buf, 2, do_write); - - ap->hsm_task_state = HSM_ST_LAST; - return; -@@ -3246,7 +3387,7 @@ - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - - /* do the actual data transfer */ -- ata_data_xfer(ap, buf, count, do_write); -+ ap->ops->data_xfer(ap, qc->dev, buf, count, do_write); - - kunmap(page); - -@@ -3955,14 +4096,15 @@ - - void ata_bmdma_irq_clear(struct ata_port *ap) - { -- if (ap->flags & ATA_FLAG_MMIO) { -- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; -- writeb(readb(mmio), mmio); -- } else { -- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; -- outb(inb(addr), addr); -- } -- -+ if (ap->ioaddr.bmdma_addr) { -+ if (ap->flags & ATA_FLAG_MMIO) { -+ void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; -+ writeb(readb(mmio), mmio); -+ } else { -+ unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; -+ outb(inb(addr), addr); -+ } -+ } - } - - -@@ -4093,9 +4235,9 @@ - - #ifdef ATA_IRQ_TRAP - if ((ap->stats.idle_irq % 1000) == 0) { -- handled = 1; - ata_irq_ack(ap, 0); /* debug trap */ - printk(KERN_WARNING "ata%d: irq trap\n", ap->id); -+ return 1; - } - #endif - return 0; /* irq not handled */ -@@ -4201,12 +4343,12 @@ - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; -- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); -+ ap->ops->data_xfer(ap, qc->dev, qc->cdb, ap->cdb_len, 1); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) - ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); - } else { -- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); -+ ap->ops->data_xfer(ap, qc->dev, qc->cdb, ap->cdb_len, 1); - - /* PIO commands are handled by polling */ - ap->hsm_task_state = HSM_ST; -@@ -4512,7 +4654,7 @@ - * Number of ports registered. Zero on error (no ports registered). - */ - --int ata_device_add(const struct ata_probe_ent *ent) -+int ata_device_add(struct ata_probe_ent *ent) - { - unsigned int count = 0, i; - struct device *dev = ent->dev; -@@ -4532,6 +4674,9 @@ - host_set->mmio_base = ent->mmio_base; - host_set->private_data = ent->private_data; - host_set->ops = ent->port_ops; -+ host_set->host_set_flags = ent->host_set_flags; -+ -+ ent->host_set = host_set; - - /* register each port bound to this device */ - for (i = 0; i < ent->n_ports; i++) { -@@ -4543,6 +4688,14 @@ - goto err_out; - - host_set->ports[i] = ap; -+ -+ /* Tidy up if we have no bus master base -+ Not sure this is the right spot to do it */ -+ if (ap->ioaddr.bmdma_addr == 0) { -+ ap->udma_mask = 0; -+ ap->mwdma_mask = 0; -+ } -+ - xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | - (ap->mwdma_mask << ATA_SHIFT_MWDMA) | - (ap->pio_mask << ATA_SHIFT_PIO); -@@ -4559,6 +4712,7 @@ - ent->irq); - - ata_chk_status(ap); -+ /* This last call probably should be conditional on bmdma */ - host_set->ops->irq_clear(ap); - count++; - } -@@ -4612,7 +4766,8 @@ - ata_scsi_scan_host(ap); - } - -- dev_set_drvdata(dev, host_set); -+ if(dev) -+ dev_set_drvdata(dev, host_set); - - VPRINTK("EXIT, returning %u\n", ent->n_ports); - return ent->n_ports; /* success */ -@@ -4786,6 +4941,7 @@ - { - struct ata_probe_ent *probe_ent = - ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); -+ unsigned long bmdma; - int p = 0; - - if (!probe_ent) -@@ -4800,7 +4956,13 @@ - probe_ent->port[p].altstatus_addr = - probe_ent->port[p].ctl_addr = - pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; -- probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); -+ bmdma = pci_resource_start(pdev, 4); -+ -+ if (bmdma) { -+ if (inb(bmdma + 2) & 0x80) -+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; -+ probe_ent->port[p].bmdma_addr = bmdma; -+ } - ata_std_ports(&probe_ent->port[p]); - p++; - } -@@ -4810,7 +4972,14 @@ - probe_ent->port[p].altstatus_addr = - probe_ent->port[p].ctl_addr = - pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; -- probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; -+ bmdma = pci_resource_start(pdev, 4); -+ -+ if (bmdma) { -+ bmdma += 8; -+ if(inb(bmdma + 2) & 0x80) -+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; -+ probe_ent->port[p].bmdma_addr = bmdma; -+ } - ata_std_ports(&probe_ent->port[p]); - p++; - } -@@ -4822,6 +4991,7 @@ - static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) - { - struct ata_probe_ent *probe_ent; -+ unsigned long bmdma; - - probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); - if (!probe_ent) -@@ -4847,7 +5017,13 @@ - probe_ent->port[0].ctl_addr = 0x376; - break; - } -- probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4) + 8 * port_num; -+ bmdma = pci_resource_start(pdev, 4); -+ if(bmdma != 0) { -+ bmdma += 8 * port_num; -+ probe_ent->port[0].bmdma_addr = bmdma; -+ if (inb(bmdma + 2) & 0x80) -+ probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; -+ } - ata_std_ports(&probe_ent->port[0]); - return probe_ent; - } -@@ -5088,6 +5264,33 @@ - pci_set_master(pdev); - return 0; - } -+ -+/** -+ * ata_pci_clear_simplex - attempt to kick device out of simplex -+ * @pdev: PCI device -+ * -+ * Some PCI ATA devices report simplex mode but in fact can be told to -+ * enter non simplex mode. This implements the neccessary logic to -+ * perform the task on such devices. Calling it on other devices will -+ * have -undefined- behaviour. -+ */ -+ -+int ata_pci_clear_simplex(struct pci_dev *pdev) -+{ -+ unsigned long bmdma = pci_resource_start(pdev, 4); -+ u8 simplex; -+ -+ if (bmdma == 0) -+ return -ENOENT; -+ -+ simplex = inb(bmdma + 0x02); -+ outb(simplex & 0x60, bmdma + 0x02); -+ simplex = inb(bmdma + 0x02); -+ if (simplex & 0x80) -+ return -EOPNOTSUPP; -+ return 0; -+} -+ - #endif /* CONFIG_PCI */ - - -@@ -5165,6 +5368,10 @@ - EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); - EXPORT_SYMBOL_GPL(ata_bmdma_status); - EXPORT_SYMBOL_GPL(ata_bmdma_stop); -+EXPORT_SYMBOL_GPL(ata_mmio_data_xfer); -+EXPORT_SYMBOL_GPL(ata_pio_data_xfer); -+EXPORT_SYMBOL_GPL(ata_mmio_data_xfer_noirq); -+EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq); - EXPORT_SYMBOL_GPL(ata_port_probe); - EXPORT_SYMBOL_GPL(sata_phy_reset); - EXPORT_SYMBOL_GPL(__sata_phy_reset); -@@ -5182,6 +5389,7 @@ - EXPORT_SYMBOL_GPL(ata_dev_config); - EXPORT_SYMBOL_GPL(ata_scsi_simulate); - -+EXPORT_SYMBOL_GPL(ata_dev_pair); - EXPORT_SYMBOL_GPL(ata_pio_need_iordy); - EXPORT_SYMBOL_GPL(ata_timing_compute); - EXPORT_SYMBOL_GPL(ata_timing_merge); -@@ -5194,6 +5402,8 @@ - EXPORT_SYMBOL_GPL(ata_pci_remove_one); - EXPORT_SYMBOL_GPL(ata_pci_device_suspend); - EXPORT_SYMBOL_GPL(ata_pci_device_resume); -+EXPORT_SYMBOL_GPL(ata_pci_clear_simplex); -+ - #endif /* CONFIG_PCI */ - - EXPORT_SYMBOL_GPL(ata_device_suspend); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/libata-scsi.c linux-2.6.16-rc6/drivers/scsi/libata-scsi.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/libata-scsi.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/libata-scsi.c 2006-03-13 14:03:15.000000000 +0000 -@@ -511,13 +511,11 @@ - printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", - id, drv_stat); - -- /* For our last chance pick, use medium read error because -- * it's much more common than an ATA drive telling you a write -- * has failed. -- */ -- *sk = MEDIUM_ERROR; -- *asc = 0x11; /* "unrecovered read error" */ -- *ascq = 0x04; /* "auto-reallocation failed" */ -+ /* We need a sensible error return here, which is tricky, and one -+ that won't cause people to do things like return a disk wrongly */ -+ *sk = ABORTED_COMMAND; -+ *asc = 0x00; -+ *ascq = 0x00; - - translate_done: - printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " -@@ -1144,14 +1142,20 @@ - if ((block >> 48) || (n_block > 65536)) - goto out_of_range; - -- /* use LBA48 */ -- tf->flags |= ATA_TFLAG_LBA48; -- -- tf->hob_nsect = (n_block >> 8) & 0xff; -- -- tf->hob_lbah = (block >> 40) & 0xff; -- tf->hob_lbam = (block >> 32) & 0xff; -- tf->hob_lbal = (block >> 24) & 0xff; -+ /* The request -may- be too large for LBA28. */ -+ if ((block >> 28) || (n_block > 256)) { -+ /* use LBA48 */ -+ tf->flags |= ATA_TFLAG_LBA48; -+ -+ tf->hob_nsect = (n_block >> 8) & 0xff; -+ -+ tf->hob_lbah = (block >> 40) & 0xff; -+ tf->hob_lbam = (block >> 32) & 0xff; -+ tf->hob_lbal = (block >> 24) & 0xff; -+ } else { -+ /* Issue LBA28 whenever we can as it is faster for PATA */ -+ tf->device |= (block >> 24) & 0xf; -+ } - } else { - /* use LBA28 */ - -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/Makefile linux-2.6.16-rc6/drivers/scsi/Makefile ---- linux.vanilla-2.6.16-rc6/drivers/scsi/Makefile 2006-03-13 14:00:13.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/Makefile 2006-02-17 18:20:44.000000000 +0000 -@@ -139,6 +139,42 @@ - obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o - obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o - -+obj-$(CONFIG_SCSI_PATA_ALI) += libata.o pata_ali.o -+obj-$(CONFIG_SCSI_PATA_AMD) += libata.o pata_amd.o -+obj-$(CONFIG_SCSI_PATA_ARTOP) += libata.o pata_artop.o -+obj-$(CONFIG_SCSI_PATA_ATIIXP) += libata.o pata_atiixp.o -+obj-$(CONFIG_SCSI_PATA_CMD64X) += libata.o pata_cmd64x.o -+obj-$(CONFIG_SCSI_PATA_CS5520) += libata.o pata_cs5520.o -+obj-$(CONFIG_SCSI_PATA_CS5530) += libata.o pata_cs5530.o -+obj-$(CONFIG_SCSI_PATA_CS5535) += libata.o pata_cs5535.o -+obj-$(CONFIG_SCSI_PATA_CYPRESS) += libata.o pata_cypress.o -+obj-$(CONFIG_SCSI_PATA_EFAR) += libata.o pata_efar.o -+obj-$(CONFIG_SCSI_PATA_ISAPNP) += libata.o pata_isapnp.o -+obj-$(CONFIG_SCSI_PATA_HPT37X) += libata.o pata_hpt37x.o -+obj-$(CONFIG_SCSI_PATA_HPT3X2N) += libata.o pata_hpt3x2n.o -+obj-$(CONFIG_SCSI_PATA_HPT3X3) += libata.o pata_hpt34x.o -+obj-$(CONFIG_SCSI_PATA_IT8172) += libata.o pata_it8172.o -+obj-$(CONFIG_SCSI_PATA_IT821X) += libata.o pata_it821x.o -+obj-$(CONFIG_SCSI_PATA_MPIIX) += libata.o pata_mpiix.o -+obj-$(CONFIG_SCSI_PATA_NETCELL) += libata.o pata_netcell.o -+obj-$(CONFIG_SCSI_PATA_NS87410) += libata.o pata_ns87410.o -+obj-$(CONFIG_SCSI_PATA_OLDPIIX) += libata.o pata_oldpiix.o -+obj-$(CONFIG_SCSI_PATA_OPTI) += libata.o pata_opti.o -+obj-$(CONFIG_SCSI_PATA_PCMCIA) += libata.o pata_pcmcia.o -+obj-$(CONFIG_SCSI_PATA_PDC_OLD) += libata.o pata_pdc202xx_old.o -+obj-$(CONFIG_SCSI_PATA_QDI) += libata.o pata_qdi.o -+obj-$(CONFIG_SCSI_PATA_RADISYS) += libata.o pata_radisys.o -+obj-$(CONFIG_SCSI_PATA_RZ1000) += libata.o pata_rz1000.o -+obj-$(CONFIG_SCSI_PATA_SERVERWORKS) += libata.o pata_serverworks.o -+obj-$(CONFIG_SCSI_PATA_SC1200) += libata.o pata_sc1200.o -+obj-$(CONFIG_SCSI_PATA_SIL680) += libata.o pata_sil680.o -+obj-$(CONFIG_SCSI_PATA_SIS) += libata.o pata_sis.o -+obj-$(CONFIG_SCSI_PATA_TRIFLEX) += libata.o pata_triflex.o -+obj-$(CONFIG_SCSI_PATA_VIA) += libata.o pata_via.o -+obj-$(CONFIG_SCSI_PATA_WINBOND) += libata.o pata_sl82c105.o -+obj-$(CONFIG_SCSI_ATA_GENERIC) += libata.o ata_generic.o -+obj-$(CONFIG_SCSI_PATA_LEGACY) += libata.o pata_legacy.o -+ - obj-$(CONFIG_ARM) += arm/ - - obj-$(CONFIG_CHR_DEV_ST) += st.o -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_ali.c linux-2.6.16-rc6/drivers/scsi/pata_ali.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_ali.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_ali.c 2006-02-27 16:59:35.000000000 +0000 -@@ -0,0 +1,624 @@ -+/* -+ * ata-ali.c - ALI 15x3 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based in part upon -+ * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 -+ * -+ * Copyright (C) 1998-2000 Michel Aubry, Maintainer -+ * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer -+ * Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer -+ * -+ * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) -+ * May be copied or modified under the terms of the GNU General Public License -+ * Copyright (C) 2002 Alan Cox <alan@redhat.com> -+ * ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw> -+ * -+ * Documentation -+ * Chipset documentation available under NDA only -+ * -+ * TODO/CHECK -+ * Cannot have ATAPI on both master & slave for rev < c2 (???) but -+ * otherwise should do atapi DMA. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "ali" -+#define DRV_VERSION "0.3" -+ -+/** -+ * ali_c2_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection for C2 and later revisions -+ */ -+ -+static int ali_c2_cable_detect(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 ata66; -+ -+ /* Certain laptops use short but suitable cables and don't -+ implement the detect logic */ -+ -+ /* Fujitsu P2000 */ -+ if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF) -+ return ATA_CBL_PATA80; -+ -+ /* Host view cable detect 0x4A bit 0 primary bit 1 secondary -+ Bit set for 40 pin */ -+ pci_read_config_byte(pdev, 0x4A, &ata66); -+ if (ata66 & (1 << ap->hard_port_no)) -+ return ATA_CBL_PATA40; -+ else -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * ali_early_phy_reset - reset for eary chip -+ * @ap: ATA port -+ * -+ * Handle the reset callback for the later chips with cable detect -+ */ -+ -+static void ali_c2_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ali_c2_cable_detect(ap); -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * ali_early_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection for older chipsets. This turns out to be -+ * rather easy to implement -+ */ -+ -+static int ali_early_cable_detect(struct ata_port *ap) { -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * ali_early_phy_reset - reset for eary chip -+ * @ap: ATA port -+ * -+ * Handle the reset callback for the early (pre cable detect) chips. -+ */ -+ -+static void ali_early_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ali_early_cable_detect(ap); -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * ali_20_filter - filter for earlier ALI DMA -+ * @ap: ALi ATA port -+ * @adev: attached device -+ * -+ * Ensure that we do not do DMA on CD devices. We may be able to -+ * fix that later on. Also ensure we do not do UDMA on WDC drives -+ */ -+ -+static unsigned int ali_20_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ char model_num[40]; -+ /* No DMA on CD for now */ -+ if (adev->class != ATA_DEV_ATA && shift != ATA_SHIFT_PIO) -+ return 0; -+ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ -+ ata_dev_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); -+ if (strstr(model_num, "WDC")) -+ return 0; -+ return mask; -+} -+ -+/** -+ * ali_fifo_control - FIFO manager -+ * @ap: ALi channel to control -+ * @adev: device for FIFO control -+ * @on: 0 for off 1 for on -+ * -+ * Enable or disable the FIFO on a given device. Because of the way the -+ * ALi FIFO works it provides a boost on ATA disk but can be confused by -+ * ATAPI and we must therefore manage it. -+ */ -+ -+static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int on) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int pio_fifo = 0x54 + ap->hard_port_no; -+ u8 fifo; -+ int shift = 4 * adev->devno; -+ -+ /* Bits 3:2 (7:6 for slave) control the PIO. 00 is off 01 -+ is on. The FIFO must not be used for ATAPI. We preserve -+ BIOS set thresholds */ -+ pci_read_config_byte(pdev, pio_fifo, &fifo); -+ fifo &= ~(0x0C << shift); -+ if (on) -+ fifo |= (on << shift); -+ pci_write_config_byte(pdev, pio_fifo, fifo); -+} -+ -+/** -+ * ali_program_modes - load mode registers -+ * @ap: ALi channel to load -+ * @adev: Device the timing is for -+ * @cmd: Command timing -+ * @data: Data timing -+ * @udma: UDMA timing or zero for off -+ * -+ * Loads the timing registers for cmd/data and disable UDMA if -+ * udma is zero. If udma is set then load and enable the UDMA -+ * timing but do not touch the command/data timing. -+ */ -+ -+static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, struct ata_timing *t, u8 ultra) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int cas = 0x58 + 4 * ap->hard_port_no; /* Command timing */ -+ int cbt = 0x59 + 4 * ap->hard_port_no; /* Command timing */ -+ int drwt = 0x5A + 4 * ap->hard_port_no + adev->devno; /* R/W timing */ -+ int udmat = 0x56 + ap->hard_port_no; /* UDMA timing */ -+ int shift = 4 * adev->devno; -+ u8 udma; -+ -+ if (t != NULL) { -+ t->setup = FIT(t->setup, 1, 8) & 7; -+ t->act8b = FIT(t->act8b, 1, 8) & 7; -+ t->rec8b = FIT(t->rec8b, 1, 16) & 15; -+ t->active = FIT(t->active, 1, 8) & 7; -+ t->recover = FIT(t->recover, 1, 16) & 15; -+ -+ pci_write_config_byte(pdev, cas, t->setup); -+ pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b); -+ pci_write_config_byte(pdev, drwt, (t->active << 4) | t->recover); -+ } -+ -+ /* Set up the UDMA enable */ -+ pci_read_config_byte(pdev, udmat, &udma); -+ udma &= ~(0x0F << shift); -+ udma |= ultra << shift; -+ pci_write_config_byte(pdev, udmat, udma); -+} -+ -+/** -+ * ali_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the ALi registers for PIO mode. FIXME: add timings for -+ * PIO5. -+ */ -+ -+static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ struct ata_timing t; -+ unsigned long T = 1000000000 / 33333; /* PCI clock based */ -+ -+ ata_timing_compute(adev, adev->pio_mode, &t, T, 1); -+ if (pair) { -+ struct ata_timing p; -+ ata_timing_compute(pair, pair->pio_mode, &p, T, 1); -+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); -+ if (pair->dma_mode) { -+ ata_timing_compute(pair, pair->dma_mode, &p, T, 1); -+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); -+ } -+ } -+ -+ /* PIO FIFO is only permitted on ATA disk */ -+ if (adev->class != ATA_DEV_ATA) -+ ali_fifo_control(ap, adev, 0); -+ ali_program_modes(ap, adev, &t, 0); -+ if (adev->class == ATA_DEV_ATA) -+ ali_fifo_control(ap, adev, 0x04); -+ -+} -+ -+/** -+ * ali_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * FIXME: MWDMA timings -+ */ -+ -+static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD }; -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ struct ata_timing t; -+ unsigned long T = 1000000000 / 33333; /* PCI clock based */ -+ -+ -+ if (adev->class == ATA_DEV_ATA) -+ ali_fifo_control(ap, adev, 0x08); -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ ali_program_modes(ap, adev, NULL, udma_timing[adev->dma_mode - XFER_UDMA_0]); -+ } else { -+ ata_timing_compute(adev, adev->dma_mode, &t, T, 1); -+ if (pair) { -+ struct ata_timing p; -+ ata_timing_compute(pair, pair->pio_mode, &p, T, 1); -+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); -+ if (pair->dma_mode) { -+ ata_timing_compute(pair, pair->dma_mode, &p, T, 1); -+ ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP|ATA_TIMING_8BIT); -+ } -+ } -+ ali_program_modes(ap, adev, &t, 0); -+ } -+} -+ -+/** -+ * ali_lock_sectors - Keep older devices to 255 sector mode -+ * @ap: ATA port -+ * @adev: Device -+ * -+ * Called during the bus probe for each device that is found. We use -+ * this call to lock the sector count of the device to 255 or less on -+ * older ALi controllers. If we didn't do this then large I/O's would -+ * require LBA48 commands which the older ALi requires are issued by -+ * slower PIO methods -+ */ -+ -+static void ali_lock_sectors(struct ata_port *ap, struct ata_device *adev) -+{ -+ if(ap->host->max_sectors > 255) { -+ ap->host->max_sectors = 255; -+ ap->host->hostt->max_sectors = 255; -+ } -+ adev->flags |= ATA_DFLAG_LOCK_SECTORS; -+} -+ -+static struct scsi_host_template ali_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ /* Keep LBA28 counts so large I/O's don't turn LBA48 and PIO -+ with older controllers. Not locked so will grow on C5 or later */ -+ .max_sectors = 255, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+/* -+ * Port operations for PIO only ALi -+ */ -+ -+static struct ata_port_operations ali_early_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = ali_set_piomode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = ali_early_phy_reset, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Port operations for DMA capable ALi without cable -+ * detect -+ */ -+static struct ata_port_operations ali_20_port_ops = { -+ .port_disable = ata_port_disable, -+ -+ .set_piomode = ali_set_piomode, -+ .set_dmamode = ali_set_dmamode, -+ .mode_filter = ali_20_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ .dev_config = ali_lock_sectors, -+ -+ .phy_reset = ali_early_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Port operations for DMA capable ALi with cable detect -+ */ -+static struct ata_port_operations ali_c2_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = ali_set_piomode, -+ .set_dmamode = ali_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ .dev_config = ali_lock_sectors, -+ -+ .phy_reset = ali_c2_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Port operations for DMA capable ALi with cable detect and LBA48 -+ */ -+static struct ata_port_operations ali_c5_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = ali_set_piomode, -+ .set_dmamode = ali_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = ali_c2_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * ali_init_one - discovery callback -+ * @pdev: PCI device ID -+ * @id: PCI table info -+ * -+ * An ALi IDE interface has been discovered. Figure out what revision -+ * and perform configuration work before handing it to the ATA layer -+ */ -+ -+static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info_early = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .port_ops = &ali_early_port_ops -+ }; -+ /* Revision 0x20 added DMA */ -+ static struct ata_port_info info_20 = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, -+ .pio_mask = 0x1f, -+ /*.mwdma_mask = 0x07,*/ -+ .port_ops = &ali_20_port_ops -+ }; -+ /* Revision 0x20 with support logic added UDMA */ -+ static struct ata_port_info info_20_udma = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, -+ .pio_mask = 0x1f, -+ /*.mwdma_mask = 0x07, */ -+ .udma_mask = 0x07, /* UDMA33 */ -+ .port_ops = &ali_20_port_ops -+ }; -+ /* Revision 0xC2 adds UDMA66 */ -+ static struct ata_port_info info_c2 = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, -+ .pio_mask = 0x1f, -+ /*.mwdma_mask = 0x07, */ -+ .udma_mask = 0x1f, -+ .port_ops = &ali_c2_port_ops -+ }; -+ /* Revision 0xC3 is UDMA100 */ -+ static struct ata_port_info info_c3 = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, -+ .pio_mask = 0x1f, -+ /* .mwdma_mask = 0x07, */ -+ .udma_mask = 0x3f, -+ .port_ops = &ali_c2_port_ops -+ }; -+ /* Revision 0xC4 is UDMA133 */ -+ static struct ata_port_info info_c4 = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, -+ .pio_mask = 0x1f, -+ /* .mwdma_mask = 0x07, */ -+ .udma_mask = 0x7f, -+ .port_ops = &ali_c2_port_ops -+ }; -+ /* Revision 0xC5 is UDMA133 with LBA48 DMA */ -+ static struct ata_port_info info_c5 = { -+ .sht = &ali_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ /* .mwdma_mask = 0x07, */ -+ .udma_mask = 0x7f, -+ .port_ops = &ali_c5_port_ops -+ }; -+ -+ static struct ata_port_info *port_info[2]; -+ u8 rev, tmp; -+ struct pci_dev *north, *isa_bridge; -+ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); -+ -+ /* -+ * The chipset revision selects the driver operations and -+ * mode data. -+ */ -+ -+ if (rev < 0x20) { -+ port_info[0] = port_info[1] = &info_early; -+ } else if (rev < 0xC2) { -+ /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */ -+ pci_read_config_byte(pdev, 0x4B, &tmp); -+ /* Clear CD-ROM DMA write bit */ -+ tmp &= 0x7F; -+ pci_write_config_byte(pdev, 0x4B, tmp); -+ port_info[0] = port_info[1] = &info_20; -+ } else if (rev == 0xC2) { -+ port_info[0] = port_info[1] = &info_c2; -+ } else if (rev == 0xC3) { -+ port_info[0] = port_info[1] = &info_c3; -+ } else if (rev == 0xC4) { -+ port_info[0] = port_info[1] = &info_c4; -+ } else -+ port_info[0] = port_info[1] = &info_c5; -+ -+ if (rev >= 0xC2) { -+ /* Enable cable detection logic */ -+ pci_read_config_byte(pdev, 0x4B, &tmp); -+ pci_write_config_byte(pdev, 0x4B, tmp | 0x08); -+ } -+ -+ north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0)); -+ isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); -+ -+ if (north && north->vendor == PCI_VENDOR_ID_AL) { -+ /* Configure the ALi bridge logic. For non ALi rely on BIOS. -+ Set the south bridge enable bit */ -+ pci_read_config_byte(isa_bridge, 0x79, &tmp); -+ if (rev == 0xC2) -+ pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04); -+ else if (rev > 0xC2) -+ pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02); -+ } -+ -+ if (rev >= 0x20) { -+ if (rev < 0xC2) { -+ /* Are we paired with a UDMA capable chip */ -+ pci_read_config_byte(isa_bridge, 0x5E, &tmp); -+ if ((tmp & 0x1E) == 0x12) -+ port_info[0] = port_info[1] = &info_20_udma; -+ } -+ /* -+ * CD_ROM DMA on (0x53 bit 0). Enable this even if we want -+ * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control -+ * via 0x54/55. -+ */ -+ pci_read_config_byte(pdev, 0x53, &tmp); -+ if (rev == 0x20) -+ tmp &= ~0x02; -+ tmp |= 0x01; /* CD_ROM enable for DMA */ -+ pci_write_config_byte(pdev, 0x53, tmp); -+ } -+ -+ pci_dev_put(isa_bridge); -+ pci_dev_put(north); -+ -+ ata_pci_clear_simplex(pdev); -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static struct pci_device_id ali[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229), }, -+ { 0, }, -+}; -+ -+static struct pci_driver ali_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = ali, -+ .probe = ali_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init ali_init(void) -+{ -+ return pci_register_driver(&ali_pci_driver); -+} -+ -+ -+static void __exit ali_exit(void) -+{ -+ pci_unregister_driver(&ali_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for ALi PATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, ali); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ali_init); -+module_exit(ali_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_amd.c linux-2.6.16-rc6/drivers/scsi/pata_amd.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_amd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_amd.c 2006-02-16 15:37:39.000000000 +0000 -@@ -0,0 +1,650 @@ -+/* -+ * pata_amd.c - AMD PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based on pata-sil680. Errata information is taken from data sheets -+ * and the amd74xx.c driver by Vojtech Pavlik. Nvidia SATA devices are -+ * claimed by sata-nv.c. -+ * -+ * TODO: -+ * Nvidia support here or seperated ? -+ * Debug cable detect -+ * Variable system clock when/if it makes sense -+ * Power management on ports -+ * -+ * -+ * Documentation publically available. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_amd" -+#define DRV_VERSION "0.1.3" -+ -+/** -+ * timing_setup - shared timing computation and load -+ * @ap: ATA port being set up -+ * @adev: drive being configured -+ * @offset: port offset -+ * @speed: target speed -+ * @clock: clock multiplier (number of times 33MHz for this part) -+ * -+ * Perform the actual timing set up for Nvidia or AMD PATA devices. -+ * The actual devices vary so they all call into this helper function -+ * providing the clock multipler and offset (because AMD and Nvidia put -+ * the ports at different locations). -+ */ -+ -+static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offset, int speed, int clock) -+{ -+ static const unsigned char amd_cyc2udma[] = { -+ 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 -+ }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct ata_device *peer = ata_dev_pair(ap, adev); -+ int dn = ap->hard_port_no * 2 + adev->devno; -+ struct ata_timing at, apeer; -+ int T, UT; -+ const int amd_clock = 33333; /* KHz. */ -+ u8 t; -+ -+ T = 1000000000 / amd_clock; -+ UT = T / min_t(int, max_t(int, clock, 1), 2); -+ -+ if (ata_timing_compute(adev, speed, &at, T, UT) < 0) { -+ dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", speed); -+ return; -+ } -+ -+ if (peer) { -+ /* This may be over conservative */ -+ if (peer->dma_mode) { -+ ata_timing_compute(peer, peer->dma_mode, &apeer, T, UT); -+ ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT); -+ } -+ ata_timing_compute(peer, peer->pio_mode, &apeer, T, UT); -+ ata_timing_merge(&apeer, &at, &at, ATA_TIMING_8BIT); -+ } -+ -+ if (speed == XFER_UDMA_5 && amd_clock <= 33333) at.udma = 1; -+ if (speed == XFER_UDMA_6 && amd_clock <= 33333) at.udma = 15; -+ -+ /* -+ * Now do the setup work -+ */ -+ -+ /* Configure the address set up timing */ -+ pci_read_config_byte(pdev, offset + 0x0C, &t); -+ t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(at.setup, 1, 4) - 1) << ((3 - dn) << 1)); -+ pci_write_config_byte(pdev, offset + 0x0C , t); -+ -+ /* Configure the 8bit I/O timing */ -+ pci_write_config_byte(pdev, offset + 0x0E + (1 - (dn >> 1)), -+ ((FIT(at.act8b, 1, 16) - 1) << 4) | (FIT(at.rec8b, 1, 16) - 1)); -+ -+ /* Drive timing */ -+ pci_write_config_byte(pdev, offset + 0x08 + (3 - dn), -+ ((FIT(at.active, 1, 16) - 1) << 4) | (FIT(at.recover, 1, 16) - 1)); -+ -+ switch (clock) { -+ case 1: -+ t = at.udma ? (0xc0 | (FIT(at.udma, 2, 5) - 2)) : 0x03; -+ break; -+ -+ case 2: -+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 2, 10)]) : 0x03; -+ break; -+ -+ case 3: -+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 10)]) : 0x03; -+ break; -+ -+ case 4: -+ t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 15)]) : 0x03; -+ break; -+ -+ default: -+ return; -+ } -+ -+ /* UDMA timing */ -+ pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t); -+} -+ -+/** -+ * amd_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection. The BIOS stores this in PCI config -+ * space for us. -+ */ -+ -+static int amd_cable_detect(struct ata_port *ap) { -+ static u32 bitmask[2] = {0x00030000, 0x00C00000}; -+ u32 ata66; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_dword(pdev, 0x42, &ata66); -+ if (ata66 & bitmask[ap->hard_port_no]) -+ return ATA_CBL_PATA80; -+ else -+ return ATA_CBL_PATA40; -+ -+} -+ -+static void amd_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits amd_enable_bits[] = { -+ { 0x40, 1, 0x02, 0x02 }, -+ { 0x40, 1, 0x01, 0x01 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &amd_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = amd_cable_detect(ap); -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * amd33_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the AMD registers for PIO mode. -+ */ -+ -+static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->pio_mode, 1); -+} -+ -+static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->pio_mode, 2); -+} -+ -+static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->pio_mode, 3); -+} -+ -+static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->pio_mode, 4); -+} -+ -+/** -+ * amd33_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the MWDMA/UDMA modes for the AMD and Nvidia -+ * chipset. -+ */ -+ -+static void amd33_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->dma_mode, 1); -+} -+ -+static void amd66_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->dma_mode, 2); -+} -+ -+static void amd100_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->dma_mode, 3); -+} -+ -+static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x40, adev->dma_mode, 4); -+} -+ -+ -+/** -+ * nv_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection. The BIOS stores this in PCI config -+ * space for us. -+ */ -+ -+static int nv_cable_detect(struct ata_port *ap) { -+ static u32 bitmask[2] = {0x00030000, 0x00C00000}; -+ u32 ata66; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_dword(pdev, 0x52, &ata66); -+ if (ata66 & bitmask[ap->hard_port_no]) -+ return ATA_CBL_PATA80; -+ else -+ return ATA_CBL_PATA40; -+ -+} -+ -+static void nv_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = nv_cable_detect(ap); -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * nv100_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the AMD registers for PIO mode. -+ */ -+ -+static void nv100_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x50, adev->pio_mode, 3); -+} -+ -+static void nv133_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x50, adev->pio_mode, 4); -+} -+ -+/** -+ * nv100_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the MWDMA/UDMA modes for the AMD and Nvidia -+ * chipset. -+ */ -+ -+static void nv100_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x50, adev->dma_mode, 3); -+} -+ -+static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ timing_setup(ap, adev, 0x50, adev->dma_mode, 4); -+} -+ -+static struct scsi_host_template amd_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations amd33_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = amd33_set_piomode, -+ .set_dmamode = amd33_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = amd_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations amd66_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = amd66_set_piomode, -+ .set_dmamode = amd66_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = amd_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations amd100_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = amd100_set_piomode, -+ .set_dmamode = amd100_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = amd_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations amd133_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = amd133_set_piomode, -+ .set_dmamode = amd133_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = amd_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations nv100_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = nv100_set_piomode, -+ .set_dmamode = nv100_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = nv_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations nv133_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = nv133_set_piomode, -+ .set_dmamode = nv133_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = nv_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info[10] = { -+ { /* 0: AMD 7401 */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, /* No SWDMA */ -+ .udma_mask = 0x07, /* UDMA 33 */ -+ .port_ops = &amd33_port_ops -+ }, -+ { /* 1: Early AMD7409 - no swdma */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, /* UDMA 66 */ -+ .port_ops = &amd66_port_ops -+ }, -+ { /* 2: AMD 7409, no swdma errata */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, /* UDMA 66 */ -+ .port_ops = &amd66_port_ops -+ }, -+ { /* 3: AMD 7411 */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, /* UDMA 100 */ -+ .port_ops = &amd100_port_ops -+ }, -+ { /* 4: AMD 7441 */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, /* UDMA 100 */ -+ .port_ops = &amd100_port_ops -+ }, -+ { /* 5: AMD 8111*/ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, /* UDMA 133, no swdma */ -+ .port_ops = &amd133_port_ops -+ }, -+ { /* 6: AMD 8111 UDMA 100 (Serenade) */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, /* UDMA 100, no swdma */ -+ .port_ops = &amd133_port_ops -+ }, -+ { /* 7: Nvidia Nforce */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, /* UDMA 100 */ -+ .port_ops = &nv100_port_ops -+ }, -+ { /* 8: Nvidia Nforce2 and later */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, /* UDMA 133, no swdma */ -+ .port_ops = &nv133_port_ops -+ }, -+ { /* 9: AMD CS5536 (Geode companion) */ -+ .sht = &amd_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, /* UDMA 100 */ -+ .port_ops = &amd100_port_ops -+ } -+ }; -+ static struct ata_port_info *port_info[2]; -+ static int printed_version; -+ int type = id->driver_data; -+ u8 rev; -+ u8 fifo; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); -+ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); -+ pci_read_config_byte(pdev, 0x41, &fifo); -+ -+ /* Check for AMD7409 without swdma errata and if found adjust type */ -+ if (type == 1 && rev > 0x7) -+ type = 2; -+ -+ /* Check for AMD7411 */ -+ if (type == 3) -+ /* FIFO is broken */ -+ pci_write_config_byte(pdev, 0x41, fifo & 0x0F); -+ else -+ pci_write_config_byte(pdev, 0x41, fifo | 0xF0); -+ -+ /* Serenade ? */ -+ if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD && -+ pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE) -+ type = 6; /* UDMA 100 only */ -+ -+ if (type < 3) -+ ata_pci_clear_simplex(pdev); -+ -+ /* And fire it up */ -+ -+ port_info[0] = port_info[1] = &info[type]; -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id amd[] = { -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_COBRA_7401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7409, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, -+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, -+ { 0, }, -+}; -+ -+static struct pci_driver amd_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = amd, -+ .probe = amd_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init amd_init(void) -+{ -+ return pci_register_driver(&amd_pci_driver); -+} -+ -+static void __exit amd_exit(void) -+{ -+ pci_unregister_driver(&amd_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for AMD PATA IDE"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, amd); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(amd_init); -+module_exit(amd_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_artop.c linux-2.6.16-rc6/drivers/scsi/pata_artop.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_artop.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_artop.c 2006-02-26 12:49:34.000000000 +0000 -@@ -0,0 +1,506 @@ -+/* -+ * pata_artop.c - ARTOP ATA controller driver -+ * -+ * (C) 2006 Red Hat <alan@redhat.com> -+ * -+ * Based in part on drivers/ide/pci/aec62xx.c -+ * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> -+ * 865/865R fixes for Macintosh card version from a patch to the old -+ * driver by Thibaut VARENE <varenet@parisc-linux.org> -+ * When setting the PCI latency we must set 0x80 or higher for burst -+ * performance Alessandro Zummo <alessandro.zummo@towertech.it> -+ * -+ * TODO -+ * 850 serialization once the core supports it -+ * Investigate no_dsc on 850R -+ * Clock detect -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_artop" -+#define DRV_VERSION "0.2.1" -+ -+/* -+ * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we -+ * get PCI bus speed functionality we leave this as 0. Its a variable -+ * for when we get the functionality and also for folks wanting to -+ * test stuff. -+ */ -+ -+static int clock = 0; -+ -+/** -+ * artop6210_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6210_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ const struct pci_bits artop_enable_bits[] = { -+ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ -+ { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &artop_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * artop6260_cable_detect - check for 40/80 pin -+ * @ap: Port -+ * -+ * The ARTOP hardware reports the cable detect bits in register 0x49. -+ * Nothing complicated needed here. -+ */ -+ -+static int artop6260_cable_detect(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 tmp; -+ -+ pci_read_config_byte(pdev, 0x49, &tmp); -+ if (tmp & (1 >> ap->hard_port_no)) -+ return ATA_CBL_PATA40; -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * artop6260_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6260_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ const struct pci_bits artop_enable_bits[] = { -+ { 0x4AU, 1U, 0x02UL, 0x02UL }, /* port 0 */ -+ { 0x4AU, 1U, 0x04UL, 0x04UL }, /* port 1 */ -+ }; -+ -+ /* Odd numbered device ids are the units with enable bits (the -R cards) */ -+ if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = artop6260_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * artop6210_load_piomode - Load a set of PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device -+ * @pio: PIO mode -+ * -+ * Set PIO mode for device, in host controller PCI config space. This -+ * is used both to set PIO timings in PIO mode and also to set the -+ * matching PIO clocking for UDMA, as well as the MWDMA timings. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6210_load_piomode(struct ata_port *ap, struct ata_device *adev, unsigned int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = adev->devno + 2 * ap->hard_port_no; -+ const u16 timing[2][5] = { -+ { 0x0000, 0x000A, 0x0008, 0x0303, 0x0301 }, -+ { 0x0700, 0x070A, 0x0708, 0x0403, 0x0401 } -+ -+ }; -+ /* Load the PIO timing active/recovery bits */ -+ pci_write_config_word(pdev, 0x40 + 2 * dn, timing[clock][pio]); -+} -+ -+/** -+ * artop6210_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring -+ * -+ * Set PIO mode for device, in host controller PCI config space. For -+ * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In -+ * the event UDMA is used the later call to set_dmamode will set the -+ * bits as required. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6210_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = adev->devno + 2 * ap->hard_port_no; -+ u8 ultra; -+ -+ artop6210_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -+ -+ /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */ -+ pci_read_config_byte(pdev, 0x54, &ultra); -+ ultra &= ~(3 << (2 * dn)); -+ pci_write_config_byte(pdev, 0x54, ultra); -+} -+ -+/** -+ * artop6260_load_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring -+ * @pio: PIO mode -+ * -+ * Set PIO mode for device, in host controller PCI config space. The -+ * ARTOP6260 and relatives store the timing data differently. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6260_load_piomode (struct ata_port *ap, struct ata_device *adev, unsigned int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = adev->devno + 2 * ap->hard_port_no; -+ const u8 timing[2][5] = { -+ { 0x00, 0x0A, 0x08, 0x33, 0x31 }, -+ { 0x70, 0x7A, 0x78, 0x43, 0x41 } -+ -+ }; -+ /* Load the PIO timing active/recovery bits */ -+ pci_write_config_byte(pdev, 0x40 + dn, timing[clock][pio]); -+} -+ -+/** -+ * artop6260_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring -+ * -+ * Set PIO mode for device, in host controller PCI config space. For -+ * ARTOP we must also clear the UDMA bits if we are not doing UDMA. In -+ * the event UDMA is used the later call to set_dmamode will set the -+ * bits as required. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6260_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 ultra; -+ -+ artop6260_load_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -+ -+ /* Clear the UDMA mode bits (set_dmamode will redo this if needed) */ -+ pci_read_config_byte(pdev, 0x44 + ap->hard_port_no, &ultra); -+ ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */ -+ pci_write_config_byte(pdev, 0x44 + ap->hard_port_no, ultra); -+} -+ -+/** -+ * artop6210_set_dmamode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set DMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6210_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = adev->devno + 2 * ap->hard_port_no; -+ u8 ultra; -+ -+ if (adev->dma_mode == XFER_MW_DMA_0) -+ pio = 1; -+ else -+ pio = 4; -+ -+ /* Load the PIO timing active/recovery bits */ -+ artop6210_load_piomode(ap, adev, pio); -+ -+ pci_read_config_byte(pdev, 0x54, &ultra); -+ ultra &= ~(3 << (2 * dn)); -+ -+ /* Add ultra DMA bits if in UDMA mode */ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ u8 mode = (adev->dma_mode - XFER_UDMA_0) + 1 - clock; -+ if (mode == 0) -+ mode = 1; -+ ultra |= (mode << (2 * dn)); -+ } -+ pci_write_config_byte(pdev, 0x54, ultra); -+} -+ -+/** -+ * artop6260_set_dmamode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring -+ * -+ * Set DMA mode for device, in host controller PCI config space. The -+ * ARTOP6260 and relatives store the timing data differently. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio = adev->pio_mode - XFER_PIO_0; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 ultra; -+ -+ if (adev->dma_mode == XFER_MW_DMA_0) -+ pio = 1; -+ else -+ pio = 4; -+ -+ /* Load the PIO timing active/recovery bits */ -+ artop6260_load_piomode(ap, adev, pio); -+ -+ /* Add ultra DMA bits if in UDMA mode */ -+ pci_read_config_byte(pdev, 0x44 + ap->hard_port_no, &ultra); -+ ultra &= ~(7 << (4 * adev->devno)); /* One nibble per drive */ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ u8 mode = adev->dma_mode - XFER_UDMA_0 + 1 - clock; -+ if (mode == 0) -+ mode = 1; -+ ultra |= (mode << (4 * adev->devno)); -+ } -+ pci_write_config_byte(pdev, 0x44 + ap->hard_port_no, ultra); -+} -+ -+static struct scsi_host_template artop_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations artop6210_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = artop6210_set_piomode, -+ .set_dmamode = artop6210_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = artop6210_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations artop6260_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = artop6260_set_piomode, -+ .set_dmamode = artop6260_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = artop6260_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+ -+/** -+ * artop_init_one - Register ARTOP ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in artop_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ static int printed_version; -+ static struct ata_port_info info_6210 = { -+ .sht = &artop_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = ATA_UDMA2, -+ .port_ops = &artop6210_ops, -+ }; -+ static struct ata_port_info info_626x = { -+ .sht = &artop_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = ATA_UDMA4, -+ .port_ops = &artop6260_ops, -+ }; -+ static struct ata_port_info info_626x_fast = { -+ .sht = &artop_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &artop6260_ops, -+ }; -+ struct ata_port_info *port_info[2]; -+ struct ata_port_info *info; -+ int ports = 2; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ if (id->driver_data == 0) { /* 6210 variant */ -+ info = &info_6210; -+ /* BIOS may have left us in UDMA, clear it before libata probe */ -+ pci_write_config_byte(pdev, 0x54, 0); -+ /* For the moment (also lacks dsc) */ -+ printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n"); -+ printk(KERN_WARNING "Secondary ATA ports will not be activated.\n"); -+ ports = 1; -+ } -+ else if (id->driver_data == 1) /* 6260 */ -+ info = &info_626x; -+ else if (id->driver_data == 2) { /* 6260 or 6260 + fast */ -+ unsigned long io = pci_resource_start(pdev, 4); -+ u8 reg; -+ -+ info = &info_626x; -+ if (inb(io) & 0x10) -+ info = &info_626x_fast; -+ /* Mac systems come up with some registers not set as we -+ will need them */ -+ -+ /* Clear reset & test bits */ -+ pci_read_config_byte(pdev, 0x49, ®); -+ pci_write_config_byte(pdev, 0x49, reg & ~ 0x30); -+ -+ /* PCI latency must be > 0x80 for burst mode, tweak it -+ * if required. -+ */ -+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); -+ if (reg <= 0x80) -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); -+ -+ /* Enable IRQ output and burst mode */ -+ pci_read_config_byte(pdev, 0x4a, ®); -+ pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); -+ -+ } -+ port_info[0] = port_info[1] = info; -+ return ata_pci_init_one(pdev, port_info, ports); -+} -+ -+static const struct pci_device_id artop_pci_tbl[] = { -+ { 0x1191, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0x1191, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { 0x1191, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { 0x1191, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { 0x1191, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver artop_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = artop_pci_tbl, -+ .probe = artop_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init artop_init(void) -+{ -+ return pci_register_driver(&artop_pci_driver); -+} -+ -+static void __exit artop_exit(void) -+{ -+ pci_unregister_driver(&artop_pci_driver); -+} -+ -+ -+module_init(artop_init); -+module_exit(artop_exit); -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, artop_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_atiixp.c linux-2.6.16-rc6/drivers/scsi/pata_atiixp.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_atiixp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_atiixp.c 2006-02-07 13:42:02.000000000 +0000 -@@ -0,0 +1,299 @@ -+/* -+ * pata_atiixp.c - ATI PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based on -+ * -+ * linux/drivers/ide/pci/atiixp.c Version 0.01-bart2 Feb. 26, 2004 -+ * -+ * Copyright (C) 2003 ATI Inc. <hyu@ati.com> -+ * Copyright (C) 2004 Bartlomiej Zolnierkiewicz -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_atiixp" -+#define DRV_VERSION "0.1.1" -+ -+enum { -+ ATIIXP_IDE_PIO_TIMING = 0x40, -+ ATIIXP_IDE_MWDMA_TIMING = 0x44, -+ ATIIXP_IDE_PIO_CONTROL = 0x48, -+ ATIIXP_IDE_PIO_MODE = 0x4a, -+ ATIIXP_IDE_UDMA_CONTROL = 0x54, -+ ATIIXP_IDE_UDMA_MODE = 0x56 -+}; -+ -+static void atiixp_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits atiixp_enable_bits[] = { -+ { 0x48, 1, 0x01, 0x00 }, -+ { 0x48, 1, 0x08, 0x00 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA80; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * atiixp_set_pio_timing - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called by both the pio and dma setup functions to set the controller -+ * timings for PIO transfers. We must load both the mode number and -+ * timing values into the controller. -+ */ -+ -+static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev, int pio) -+{ -+ static u8 pio_timings[5] = { 0x5D, 0x47, 0x34, 0x22, 0x20 }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = 2 * ap->hard_port_no + adev->devno; -+ -+ /* Check this is correct - the order is odd in both drivers */ -+ int timing_shift = (16 * ap->hard_port_no) + 8 * (adev->devno ^ 1); -+ u16 pio_mode_data, pio_timing_data; -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data); -+ pio_mode_data &= ~(0x7 << (4 * dn)); -+ pio_mode_data |= pio << (4 * dn); -+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data); -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data); -+ pio_mode_data &= ~(0xFF << timing_shift); -+ pio_mode_data |= (pio_timings[pio] << timing_shift); -+ pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data); -+} -+ -+/** -+ * atiixp_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. We use a shared helper for this -+ * as the DMA setup must also adjust the PIO timing information. -+ */ -+ -+static void atiixp_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ atiixp_set_pio_timing(ap, adev, adev->pio_mode - XFER_PIO_0); -+} -+ -+/** -+ * atiixp_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the DMA mode setup. We use timing tables for most -+ * modes but must tune an appropriate PIO mode to match. -+ */ -+ -+static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u8 mwdma_timings[5] = { 0x77, 0x21, 0x20 }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dma = adev->dma_mode; -+ int dn = 2 * ap->hard_port_no + adev->devno; -+ int wanted_pio; -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ u16 udma_mode_data; -+ -+ dma -= XFER_UDMA_0; -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_MODE, &udma_mode_data); -+ udma_mode_data &= ~(0x7 << (4 * dn)); -+ udma_mode_data |= dma << (4 * dn); -+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data); -+ } else { -+ u16 mwdma_timing_data; -+ /* Check this is correct - the order is odd in both drivers */ -+ int timing_shift = (16 * ap->hard_port_no) + 8 * (adev->devno ^ 1); -+ -+ dma -= XFER_MW_DMA_0; -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data); -+ mwdma_timing_data &= ~(0xFF << timing_shift); -+ mwdma_timing_data |= (mwdma_timings[dma] << timing_shift); -+ pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data); -+ } -+ /* -+ * We must now look at the PIO mode situation. We may need to -+ * adjust the PIO mode to keep the timings acceptable -+ */ -+ if (adev->dma_mode >= XFER_MW_DMA_2) -+ wanted_pio = 4; -+ else if (adev->dma_mode == XFER_MW_DMA_1) -+ wanted_pio = 3; -+ else if (adev->dma_mode == XFER_MW_DMA_0) -+ wanted_pio = 0; -+ else BUG(); -+ -+ if (adev->pio_mode != wanted_pio) -+ atiixp_set_pio_timing(ap, adev, wanted_pio); -+} -+ -+/** -+ * atiixp_bmdma_start - DMA start callback -+ * @qc: Command in progress -+ * -+ * When DMA begins we need to ensure that the UDMA control -+ * register for the channel is correctly set. -+ */ -+ -+static void atiixp_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = (2 * ap->hard_port_no) + adev->devno; -+ u16 tmp16; -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); -+ if (adev->dma_mode >= XFER_UDMA_0) -+ tmp16 |= (1 << dn); -+ else -+ tmp16 &= ~(1 << dn); -+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16); -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * atiixp_dma_stop - DMA stop callback -+ * @qc: Command in progress -+ * -+ * DMA has completed. Clear the UDMA flag as the next operations will -+ * be PIO ones not UDMA data transfer. -+ */ -+ -+static void atiixp_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = (2 * ap->hard_port_no) + qc->dev->devno; -+ u16 tmp16; -+ -+ pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); -+ tmp16 &= ~(1 << dn); -+ pci_write_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, tmp16); -+ ata_bmdma_stop(qc); -+} -+ -+static struct scsi_host_template atiixp_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations atiixp_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = atiixp_set_piomode, -+ .set_dmamode = atiixp_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = atiixp_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = atiixp_bmdma_start, -+ .bmdma_stop = atiixp_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &atiixp_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x06, /* No MWDMA0 support */ -+ .udma_mask = 0x3F, -+ .port_ops = &atiixp_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id atiixp[] = { -+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0, }, -+}; -+ -+static struct pci_driver atiixp_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = atiixp, -+ .probe = atiixp_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init atiixp_init(void) -+{ -+ return pci_register_driver(&atiixp_pci_driver); -+} -+ -+ -+static void __exit atiixp_exit(void) -+{ -+ pci_unregister_driver(&atiixp_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for ATI IXP200/300/400"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, atiixp); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(atiixp_init); -+module_exit(atiixp_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cmd64x.c linux-2.6.16-rc6/drivers/scsi/pata_cmd64x.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cmd64x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_cmd64x.c 2006-02-16 15:34:39.000000000 +0000 -@@ -0,0 +1,486 @@ -+/* -+ * pata_cmd64x.c - ATI PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based upon -+ * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 -+ * -+ * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. -+ * Note, this driver is not used at all on other systems because -+ * there the "BIOS" has done all of the following already. -+ * Due to massive hardware bugs, UltraDMA is only supported -+ * on the 646U2 and not on the 646U. -+ * -+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) -+ * Copyright (C) 1998 David S. Miller (davem@redhat.com) -+ * -+ * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> -+ * -+ * TODO -+ * Testing work -+ * Non x86 needs PIO 0 loading before we commence ident -+ * - but this belongs in libata-core -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_cmd64x" -+#define DRV_VERSION "0.1.1" -+ -+/* -+ * CMD64x specific registers definition. -+ */ -+ -+enum { -+ CFR = 0x50, -+ CFR_INTR_CH0 = 0x02, -+ CNTRL = 0x51, -+ CNTRL_DIS_RA0 = 0x40, -+ CNTRL_DIS_RA1 = 0x80, -+ CNTRL_ENA_2ND = 0x08, -+ CMDTIM = 0x52, -+ ARTTIM0 = 0x53, -+ DRWTIM0 = 0x54, -+ ARTTIM1 = 0x55, -+ DRWTIM1 = 0x56, -+ ARTTIM23 = 0x57, -+ ARTTIM23_DIS_RA2 = 0x04, -+ ARTTIM23_DIS_RA3 = 0x08, -+ ARTTIM23_INTR_CH1 = 0x10, -+ ARTTIM2 = 0x57, -+ ARTTIM3 = 0x57, -+ DRWTIM23 = 0x58, -+ DRWTIM2 = 0x58, -+ BRST = 0x59, -+ DRWTIM3 = 0x5b, -+ BMIDECR0 = 0x70, -+ MRDMODE = 0x71, -+ MRDMODE_INTR_CH0 = 0x04, -+ MRDMODE_INTR_CH1 = 0x08, -+ MRDMODE_BLK_CH0 = 0x10, -+ MRDMODE_BLK_CH1 = 0x20, -+ BMIDESR0 = 0x72, -+ UDIDETCR0 = 0x73, -+ DTPR0 = 0x74, -+ BMIDECR1 = 0x78, -+ BMIDECSR = 0x79, -+ BMIDESR1 = 0x7A, -+ UDIDETCR1 = 0x7B, -+ DTPR1 = 0x7C -+}; -+ -+/* Phee Phy Pho Phum */ -+ -+static void cmd64x_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+static void cmd648_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 r; -+ -+ /* Check cable detect bits */ -+ pci_read_config_byte(pdev, BMIDECSR, &r); -+ if (r & (1 << ap->hard_port_no)) -+ ap->cbl = ATA_CBL_PATA80; -+ else -+ ap->cbl = ATA_CBL_PATA40; -+ -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * cmd64x_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. -+ */ -+ -+static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct ata_timing t; -+ const unsigned long T = 1000000 / 33; -+ const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 }; -+ -+ u8 reg; -+ -+ /* Port layout is not logical so use a table */ -+ const u8 arttim_port[2][2] = { -+ { ARTTIM0, ARTTIM1 }, -+ { ARTTIM23, ARTTIM23 } -+ }; -+ const u8 drwtim_port[2][2] = { -+ { DRWTIM0, DRWTIM1 }, -+ { DRWTIM2, DRWTIM3 } -+ }; -+ -+ int arttim = arttim_port[ap->hard_port_no][adev->devno]; -+ int drwtim = drwtim_port[ap->hard_port_no][adev->devno]; -+ -+ -+ if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) { -+ printk(KERN_ERR DRV_NAME ": mome computation failed.\n"); -+ return; -+ } -+ if (ap->hard_port_no) { -+ /* Slave has shared address setup */ -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ -+ if (pair) { -+ struct ata_timing tp; -+ ata_timing_compute(pair, pair->pio_mode, &tp, T, 0); -+ ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); -+ } -+ } -+ -+ printk(KERN_DEBUG DRV_NAME ": active %d recovery %d setup %d.\n", -+ t.active, t.recover, t.setup); -+ if (t.recover > 16) { -+ t.active += t.recover - 16; -+ t.recover = 16; -+ } -+ if (t.active > 16) -+ t.active = 16; -+ -+ /* Now convert the clocks into values we can actually stuff into -+ the chip */ -+ -+ if (t.recover > 1) -+ t.recover--; -+ else -+ t.recover = 15; -+ -+ if (t.setup > 4) -+ t.setup = 0xC0; -+ else -+ t.setup = setup_data[t.setup]; -+ -+ t.active &= 0x0F; /* 0 = 16 */ -+ -+ /* Load setup timing */ -+ pci_read_config_byte(pdev, arttim, ®); -+ reg &= 0x3F; -+ reg |= t.setup; -+ pci_write_config_byte(pdev, arttim, reg); -+ -+ /* Load active/recovery */ -+ pci_write_config_byte(pdev, drwtim, (t.active << 4) | t.recover); -+} -+ -+/** -+ * cmd64x_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the DMA mode setup. -+ */ -+ -+static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 regU, regD; -+ -+ int pciU = UDIDETCR0 + 8 * ap->hard_port_no; -+ int pciD = BMIDESR0 + 8 * ap->hard_port_no; -+ int shift = 2 * adev->devno; -+ const u8 udma_data[] = { 0x31, 0x21, 0x11, 0x25, 0x15, 0x05 }; -+ const u8 mwdma_data[] = { 0x30, 0x20, 0x10 }; -+ -+ pci_read_config_byte(pdev, pciD, ®D); -+ pci_read_config_byte(pdev, pciU, ®U); -+ -+ regD &= ~(0x20 << shift); -+ regU &= ~(0x35 << shift); -+ -+ if (adev->dma_mode >= XFER_UDMA_0) -+ regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; -+ else -+ regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift; -+ -+ regD |= 0x20 << adev->devno; -+ -+ pci_write_config_byte(pdev, pciU, regU); -+ pci_write_config_byte(pdev, pciD, regD); -+} -+ -+/** -+ * cmd648_dma_stop - DMA stop callback -+ * @qc: Command in progress -+ * -+ * DMA has completed. -+ */ -+ -+static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 dma_intr; -+ int dma_reg = ap->hard_port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; -+ int dma_mask = ap->hard_port_no ? ARTTIM2 : CFR; -+ -+ ata_bmdma_stop(qc); -+ -+ pci_read_config_byte(pdev, dma_reg, &dma_intr); -+ pci_write_config_byte(pdev, dma_reg, dma_intr | dma_mask); -+} -+ -+/** -+ * cmd646r1_dma_stop - DMA stop callback -+ * @qc: Command in progress -+ * -+ * Stub for now while investigating the r1 quirk in the old driver. -+ */ -+ -+static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ ata_bmdma_stop(qc); -+} -+ -+static struct scsi_host_template cmd64x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations cmd64x_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cmd64x_set_piomode, -+ .set_dmamode = cmd64x_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = cmd64x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations cmd646r1_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cmd64x_set_piomode, -+ .set_dmamode = cmd64x_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = cmd64x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = cmd646r1_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations cmd648_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cmd64x_set_piomode, -+ .set_dmamode = cmd64x_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = cmd648_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = cmd648_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ u32 class_rev; -+ -+ static struct ata_port_info cmd_info[6] = { -+ { /* CMD 643 - no UDMA */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &cmd64x_port_ops -+ }, -+ { /* CMD 646 with broken UDMA */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &cmd64x_port_ops -+ }, -+ { /* CMD 646 with working UDMA */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA1, -+ .port_ops = &cmd64x_port_ops -+ }, -+ { /* CMD 646 rev 1 */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &cmd646r1_port_ops -+ }, -+ { /* CMD 648 */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA2, -+ .port_ops = &cmd648_port_ops -+ }, -+ { /* CMD 649 */ -+ .sht = &cmd64x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA3, -+ .port_ops = &cmd648_port_ops -+ } -+ }; -+ static struct ata_port_info *port_info[2], *info; -+ u8 mrdmode; -+ -+ info = &cmd_info[id->driver_data]; -+ -+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); -+ class_rev &= 0xFF; -+ -+ if (id->driver_data == 0) /* 643 */ -+ ata_pci_clear_simplex(pdev); -+ -+ if (pdev->device == PCI_DEVICE_ID_CMD_646) { -+ /* Does UDMA work ? */ -+ if (class_rev > 4) -+ info = &cmd_info[2]; -+ /* Early rev with other problems ? */ -+ else if (class_rev == 1) -+ info = &cmd_info[3]; -+ } -+ -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); -+ pci_read_config_byte(pdev, MRDMODE, &mrdmode); -+ mrdmode &= ~ 0x30; /* IRQ set up */ -+ mrdmode |= 0x02; /* Memory read line enable */ -+ pci_write_config_byte(pdev, MRDMODE, mrdmode); -+ -+ /* Force PIO 0 here.. */ -+ -+ /* PPC specific fixup copied from old driver */ -+#ifdef CONFIG_PPC -+ pci_write_config_byte(pdev, UDIDETCR0, 0xF0); -+#endif -+ -+ port_info[0] = port_info[1] = info; -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static struct pci_device_id cmd64x[] = { -+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_643, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, -+ { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, -+ { 0, }, -+}; -+ -+static struct pci_driver cmd64x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = cmd64x, -+ .probe = cmd64x_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init cmd64x_init(void) -+{ -+ return pci_register_driver(&cmd64x_pci_driver); -+} -+ -+ -+static void __exit cmd64x_exit(void) -+{ -+ pci_unregister_driver(&cmd64x_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for CMD64x series PATA controllers"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, cmd64x); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cmd64x_init); -+module_exit(cmd64x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5520.c linux-2.6.16-rc6/drivers/scsi/pata_cs5520.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5520.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_cs5520.c 2006-03-10 17:05:31.000000000 +0000 -@@ -0,0 +1,322 @@ -+/* -+ * IDE tuning and bus mastering support for the CS5510/CS5520 -+ * chipsets -+ * -+ * The CS5510/CS5520 are slightly unusual devices. Unlike the -+ * typical IDE controllers they do bus mastering with the drive in -+ * PIO mode and smarter silicon. -+ * -+ * The practical upshot of this is that we must always tune the -+ * drive for the right PIO mode. We must also ignore all the blacklists -+ * and the drive bus mastering DMA information. Also to confuse matters -+ * further we can do DMA on PIO only drives. -+ * -+ * DMA on the 5510 also requires we disable_hlt() during DMA on early -+ * revisions. -+ * -+ * *** This driver is strictly experimental *** -+ * -+ * (c) Copyright Red Hat Inc 2002 -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2, or (at your option) any -+ * later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * Documentation: -+ * Not publically available. -+ */ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "cs5520" -+#define DRV_VERSION "0.4.1" -+ -+struct pio_clocks -+{ -+ int address; -+ int assert; -+ int recovery; -+}; -+ -+static struct pio_clocks cs5520_pio_clocks[]={ -+ {3, 6, 11}, -+ {2, 5, 6}, -+ {1, 4, 3}, -+ {1, 3, 2}, -+ {1, 2, 1} -+}; -+ -+/** -+ * cs5520_set_timings - program PIO timings -+ * @ap: ATA port -+ * @adev: ATA device -+ * -+ * Program the PIO mode timings for the controller according to the pio -+ * clocking table. -+ */ -+ -+static void cs5520_set_timings(struct ata_port *ap, struct ata_device *adev, int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int slave = adev->devno; -+ -+ pio -= XFER_PIO_0; -+ -+ /* Channel command timing */ -+ pci_write_config_byte(pdev, 0x62 + ap->hard_port_no, -+ (cs5520_pio_clocks[pio].recovery << 4) | -+ (cs5520_pio_clocks[pio].assert)); -+ /* FIXME: should these use address ? */ -+ /* Read command timing */ -+ pci_write_config_byte(pdev, 0x64 + 4*ap->hard_port_no + slave, -+ (cs5520_pio_clocks[pio].recovery << 4) | -+ (cs5520_pio_clocks[pio].assert)); -+ /* Write command timing */ -+ pci_write_config_byte(pdev, 0x66 + 4*ap->hard_port_no + slave, -+ (cs5520_pio_clocks[pio].recovery << 4) | -+ (cs5520_pio_clocks[pio].assert)); -+} -+ -+/** -+ * cs5520_enable_dma - turn on DMA bits -+ * -+ * Turn on the DMA bits for this disk. Needed because the BIOS probably -+ * has not done the work for us. Belongs in the core SATA code. -+ */ -+ -+static int cs5520_enable_dma(struct ata_port *ap, struct ata_device *adev) -+{ -+ /* Set the DMA enable/disable flag */ -+ u8 reg = inb(ap->ioaddr.bmdma_addr + 0x02); -+ reg |= 1<<(adev->devno + 5); -+ outb(reg, ap->ioaddr.bmdma_addr + 0x02); -+} -+ -+/** -+ * cs5520_set_dmamode - program DMA timings -+ * @ap: ATA port -+ * @adev: ATA device -+ * -+ * Program the DMA mode timings for the controller according to the pio -+ * clocking table. Note that this device sets the DMA timings to PIO -+ * mode values. This may seem bizarre but the 5520 architecture talks -+ * PIO mode to the disk and DMA mode to the controller so the underlying -+ * transfers are PIO timed. -+ */ -+ -+static void cs5520_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static const int dma_xlate[3] = { XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 }; -+ cs5520_set_timings(ap, adev, dma_xlate[adev->dma_mode]); -+ cs5520_enable_dma(ap, adev); -+} -+ -+/** -+ * cs5520_set_piomode - program PIO timings -+ * @ap: ATA port -+ * @adev: ATA device -+ * -+ * Program the PIO mode timings for the controller according to the pio -+ * clocking table. We know pio_mode will equal dma_mode because of the -+ * CS5520 architecture. At least once we turned DMA on and wrote a -+ * mode setter. -+ */ -+ -+static void cs5520_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ cs5520_set_timings(ap, adev, adev->pio_mode); -+} -+ -+static struct scsi_host_template cs5520_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations cs5520_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cs5520_set_piomode, -+ .set_dmamode = cs5520_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ u8 pcicfg; -+ static struct ata_probe_ent probe[2]; -+ int ports = 0; -+ -+ pci_read_config_byte(dev, 0x60, &pcicfg); -+ -+ /* Check if the ATA ports are enabled */ -+ if ((pcicfg & 3) == 0) -+ return -ENODEV; -+ -+ if ((pcicfg & 0x40) == 0) { -+ printk(KERN_WARNING DRV_NAME ": DMA mode disabled. Enabling.\n"); -+ pci_write_config_byte(dev, 0x60, pcicfg | 0x40); -+ } -+ -+ /* Perform set up for DMA */ -+ if (pci_enable_device_bars(dev, 1<<2)) { -+ printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n"); -+ return -ENODEV; -+ } -+ pci_set_master(dev); -+ if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { -+ printk(KERN_ERR DRV_NAME ": unable to configure DMA mask.\n"); -+ return -ENODEV; -+ } -+ if (pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK)) { -+ printk(KERN_ERR DRV_NAME ": unable to configure consistent DMA mask.\n"); -+ return -ENODEV; -+ } -+ -+ /* We have to do our own plumbing as the PCI setup for this -+ chipset is non-standard so we can't punt to the libata code */ -+ -+ INIT_LIST_HEAD(&probe[0].node); -+ probe[0].dev = pci_dev_to_dev(dev); -+ probe[0].port_ops = &cs5520_port_ops; -+ probe[0].sht = &cs5520_sht; -+ probe[0].pio_mask = 0x1F; -+ probe[0].mwdma_mask = id->driver_data; -+ probe[0].irq = 14; -+ probe[0].irq_flags = SA_SHIRQ; -+ probe[0].host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST; -+ probe[0].legacy_mode = 1; -+ probe[0].n_ports = 1; -+ probe[0].port[0].cmd_addr = 0x1F0; -+ probe[0].port[0].ctl_addr = 0x3F6; -+ probe[0].port[0].altstatus_addr = 0x3F6; -+ probe[0].port[0].bmdma_addr = pci_resource_start(dev, 2); -+ -+ /* The secondary lurks at different addresses but is otherwise -+ the same beastie */ -+ -+ probe[1] = probe[0]; -+ INIT_LIST_HEAD(&probe[1].node); -+ probe[1].irq = 15; -+ probe[1].hard_port_no = 1; -+ probe[1].port[0].cmd_addr = 0x170; -+ probe[1].port[0].ctl_addr = 0x376; -+ probe[1].port[0].altstatus_addr = 0x376; -+ probe[1].port[0].bmdma_addr = pci_resource_start(dev, 2) + 8; -+ -+ /* Let libata fill in the port details */ -+ ata_std_ports(&probe[0].port[0]); -+ ata_std_ports(&probe[1].port[0]); -+ -+ /* Now add the ports that are active */ -+ if (pcicfg & 1) -+ ports += ata_device_add(&probe[0]); -+ if (pcicfg & 2) -+ ports += ata_device_add(&probe[1]); -+ if (ports) -+ return 0; -+ return -ENODEV; -+} -+ -+/** -+ * cs5520_remove_one - device unload -+ * @pdev: PCI device being removed -+ * -+ * Handle an unplug/unload event for a PCI device. Unload the -+ * PCI driver but do not use the default handler as we manage -+ * resources ourself and *MUST NOT* disable the device as it has -+ * other functions. -+ */ -+ -+static void __devexit cs5520_remove_one(struct pci_dev *pdev) -+{ -+ struct device *dev = pci_dev_to_dev(pdev); -+ struct ata_host_set *host_set = dev_get_drvdata(dev); -+ -+ ata_host_set_remove(host_set); -+ dev_set_drvdata(dev, NULL); -+} -+ -+/* For now keep DMA off. We can set it for all but A rev CS5510 once the -+ core ATA code can handle it */ -+ -+static struct pci_device_id pata_cs5520[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520), }, -+ { 0, }, -+}; -+ -+static struct pci_driver cs5520_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pata_cs5520, -+ .probe = cs5520_init_one, -+ .remove = cs5520_remove_one -+}; -+ -+ -+static int __init cs5520_init(void) -+{ -+ return pci_register_driver(&cs5520_pci_driver); -+} -+ -+static void __exit cs5520_exit(void) -+{ -+ pci_unregister_driver(&cs5520_pci_driver); -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Cyrix CS5510/5520"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, pata_cs5520); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cs5520_init); -+module_exit(cs5520_exit); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5530.c linux-2.6.16-rc6/drivers/scsi/pata_cs5530.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5530.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_cs5530.c 2006-03-10 17:05:20.000000000 +0000 -@@ -0,0 +1,371 @@ -+/* -+ * pata-cs5530.c - CS5530 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon cs5530.c by Mark Lord. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Loosely based on the piix & svwks drivers. -+ * -+ * Documentation: -+ * Available from AMD web site. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/dmi.h> -+ -+#define DRV_NAME "cs5530" -+#define DRV_VERSION "0.4.1" -+ -+/** -+ * cs5530_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Set our PIO requirements. This is fairly simple on the CS5530 -+ * chips. -+ */ -+ -+static void cs5530_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static unsigned int cs5530_pio_timings[2][5] = { -+ {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, -+ {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010} -+ }; -+ unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->hard_port_no; -+ u32 tuning; -+ int format; -+ -+ /* Find out which table to use */ -+ tuning = inl(base + 0x04); -+ format = (tuning & 0x80000000UL) ? 1 : 0; -+ -+ /* Now load the right timing register */ -+ if (adev->devno) -+ base += 0x08; -+ -+ outl(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base); -+} -+ -+/** -+ * cs5530_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * We cannot mix MWDMA and UDMA without reloading timings each switch -+ * master to slave. We track the last DMA setup in order to minimise -+ * reloads. -+ */ -+ -+static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned long base = ( ap->ioaddr.bmdma_addr & ~0x0F) + 0x20 + 0x10 * ap->hard_port_no; -+ u32 tuning, timing = 0; -+ u8 reg; -+ -+ /* Find out which table to use */ -+ tuning = inl(base + 0x04); -+ -+ switch(adev->dma_mode) { -+ case XFER_UDMA_0: -+ timing = 0x00921250;break; -+ case XFER_UDMA_1: -+ timing = 0x00911140;break; -+ case XFER_UDMA_2: -+ timing = 0x00911030;break; -+ case XFER_MW_DMA_0: -+ timing = 0x00077771;break; -+ case XFER_MW_DMA_1: -+ timing = 0x00012121;break; -+ case XFER_MW_DMA_2: -+ timing = 0x00002020;break; -+ default: -+ BUG(); -+ } -+ /* Merge in the PIO format bit */ -+ timing |= (tuning & 0x80000000UL); -+ if (adev->devno == 0) /* Master */ -+ outl(timing, base + 0x04); -+ else { -+ if (timing & 0x00100000) -+ tuning |= 0x00100000; /* UDMA for both */ -+ else -+ tuning &= ~0x00100000; /* MWDMA for both */ -+ outl(tuning, base + 0x04); -+ outl(timing, base + 0x0C); -+ } -+ -+ /* Set the DMA capable bit in the BMDMA area */ -+ reg = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); -+ reg |= (1 << (5 + adev->devno)); -+ outb(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); -+ -+ /* Remember the last DMA setup we did */ -+ -+ ap->private_data = adev; -+} -+ -+/** -+ * cs5530_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Specifically we have a problem that there is only -+ * one MWDMA/UDMA bit. -+ */ -+ -+static int cs5530_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ struct ata_device *prev = ap->private_data; -+ -+ /* See if the DMA settings could be wrong */ -+ if (adev->dma_mode != 0 && adev != prev && prev != NULL) { -+ /* Maybe, but do the channels match MWDMA/UDMA ? */ -+ if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || -+ (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) -+ /* Switch the mode bits */ -+ cs5530_set_dmamode(ap, adev); -+ } -+ -+ return ata_qc_issue_prot(qc); -+} -+ -+static struct scsi_host_template cs5530_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations cs5530_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cs5530_set_piomode, -+ .set_dmamode = cs5530_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = cs5530_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct dmi_system_id __initdata palmax_dmi_table[] = { -+ { -+ .ident = "Palmax PD1100", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Cyrix"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Caddis"), -+ }, -+ }, -+ { } -+}; -+ -+static int cs5530_is_palmax(void) -+{ -+ if (dmi_check_system(palmax_dmi_table)) { -+ printk(KERN_INFO "Palmax PD1100: Disabling DMA on docking port.\n"); -+ return 1; -+ } -+ return 0; -+} -+ -+/** -+ * cs5530_init_one - Initialise a CS5530 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Install a driver for the newly found CS5530 companion chip. Most of -+ * this is just housekeeping. We have to set the chip up correctly and -+ * turn off various bits of emulation magic. -+ */ -+ -+static int cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ int compiler_warning_pointless_fix; -+ struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; -+ static struct ata_port_info info = { -+ .sht = &cs5530_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x07, -+ .port_ops = &cs5530_port_ops -+ }; -+ /* The docking connector doesn't do UDMA, and it seems not MWDMA */ -+ static struct ata_port_info info_palmax_secondary = { -+ .sht = &cs5530_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .port_ops = &cs5530_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ dev = NULL; -+ while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) { -+ switch (dev->device) { -+ case PCI_DEVICE_ID_CYRIX_PCI_MASTER: -+ master_0 = pci_dev_get(dev); -+ break; -+ case PCI_DEVICE_ID_CYRIX_5530_LEGACY: -+ cs5530_0 = pci_dev_get(dev); -+ break; -+ } -+ } -+ if (!master_0) { -+ printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n"); -+ goto fail_put; -+ } -+ if (!cs5530_0) { -+ printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n"); -+ goto fail_put; -+ } -+ -+ pci_set_master(cs5530_0); -+ compiler_warning_pointless_fix = pci_set_mwi(cs5530_0); -+ -+ /* -+ * Set PCI CacheLineSize to 16-bytes: -+ * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530 -+ * -+ * Note: This value is constant because the 5530 is only a Geode companion -+ */ -+ -+ pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04); -+ -+ /* -+ * Disable trapping of UDMA register accesses (Win98 hack): -+ * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530 -+ */ -+ -+ pci_write_config_word(cs5530_0, 0xd0, 0x5006); -+ -+ /* -+ * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus: -+ * The other settings are what is necessary to get the register -+ * into a sane state for IDE DMA operation. -+ */ -+ -+ pci_write_config_byte(master_0, 0x40, 0x1e); -+ -+ /* -+ * Set max PCI burst size (16-bytes seems to work best): -+ * 16bytes: set bit-1 at 0x41 (reg value of 0x16) -+ * all others: clear bit-1 at 0x41, and do: -+ * 128bytes: OR 0x00 at 0x41 -+ * 256bytes: OR 0x04 at 0x41 -+ * 512bytes: OR 0x08 at 0x41 -+ * 1024bytes: OR 0x0c at 0x41 -+ */ -+ -+ pci_write_config_byte(master_0, 0x41, 0x14); -+ -+ /* -+ * These settings are necessary to get the chip -+ * into a sane state for IDE DMA operation. -+ */ -+ -+ pci_write_config_byte(master_0, 0x42, 0x00); -+ pci_write_config_byte(master_0, 0x43, 0xc1); -+ -+ pci_dev_put(master_0); -+ pci_dev_put(cs5530_0); -+ -+ if (cs5530_is_palmax()) -+ port_info[1] = &info_palmax_secondary; -+ -+ /* Now kick off ATA set up */ -+ return ata_pci_init_one(dev, port_info, 2); -+ -+fail_put: -+ if (master_0) -+ pci_dev_put(master_0); -+ if (cs5530_0) -+ pci_dev_put(cs5530_0); -+ return -ENODEV; -+} -+ -+static struct pci_device_id cs5530[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), }, -+ { 0, }, -+}; -+ -+static struct pci_driver cs5530_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = cs5530, -+ .probe = cs5530_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init cs5530_init(void) -+{ -+ return pci_register_driver(&cs5530_pci_driver); -+} -+ -+ -+static void __exit cs5530_exit(void) -+{ -+ pci_unregister_driver(&cs5530_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, cs5530); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cs5530_init); -+module_exit(cs5530_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5535.c linux-2.6.16-rc6/drivers/scsi/pata_cs5535.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cs5535.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_cs5535.c 2006-03-10 17:05:14.000000000 +0000 -@@ -0,0 +1,286 @@ -+/* -+ * pata-cs5535.c - CS5535 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon cs5535.c from AMD <Jens.Altmann@amd.com> as cleaned up and -+ * made readable and Linux style by Wolfgang Zuleger <wolfgang.zuleger@gmx.de -+ * and Alexander Kiausch <alex.kiausch@t-online.de> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Loosely based on the piix & svwks drivers. -+ * -+ * Documentation: -+ * Available from AMD web site. -+ * TODO -+ * Review errata to see if serializing is neccessary -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <asm/msr.h> -+ -+#define DRV_NAME "cs5535" -+#define DRV_VERSION "0.2.2" -+ -+/* -+ * The Geode (Aka Athlon GX now) uses an internal MSR based -+ * bus system for control. Demented but there you go. -+ */ -+ -+#define MSR_ATAC_BASE 0x51300000 -+#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0) -+#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01) -+#define ATAC_GLD_MSR_SMI (MSR_ATAC_BASE+0x02) -+#define ATAC_GLD_MSR_ERROR (MSR_ATAC_BASE+0x03) -+#define ATAC_GLD_MSR_PM (MSR_ATAC_BASE+0x04) -+#define ATAC_GLD_MSR_DIAG (MSR_ATAC_BASE+0x05) -+#define ATAC_IO_BAR (MSR_ATAC_BASE+0x08) -+#define ATAC_RESET (MSR_ATAC_BASE+0x10) -+#define ATAC_CH0D0_PIO (MSR_ATAC_BASE+0x20) -+#define ATAC_CH0D0_DMA (MSR_ATAC_BASE+0x21) -+#define ATAC_CH0D1_PIO (MSR_ATAC_BASE+0x22) -+#define ATAC_CH0D1_DMA (MSR_ATAC_BASE+0x23) -+#define ATAC_PCI_ABRTERR (MSR_ATAC_BASE+0x24) -+ -+#define ATAC_BM0_CMD_PRIM 0x00 -+#define ATAC_BM0_STS_PRIM 0x02 -+#define ATAC_BM0_PRD 0x04 -+ -+#define CS5535_CABLE_DETECT 0x48 -+ -+#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000UL)==0x00009172 ) -+ -+/** -+ * cs5535_cable_detect - detect cable type -+ * @ap: Port to detect on -+ * -+ * Perform cable detection for ATA66 capable cable. Return a libata -+ * cable type. -+ */ -+ -+static int cs5535_cable_detect(struct ata_port *ap) -+{ -+ u8 cable; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_byte(pdev, CS5535_CABLE_DETECT, &cable); -+ if (cable & 1) -+ return ATA_CBL_PATA80; -+ else -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * cs5535_phy_reset - reset/probe -+ * @ap: Port to reset -+ * -+ * Reset and configure a port -+ */ -+ -+static void cs5535_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = cs5535_cable_detect(ap); -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * cs5535_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Set our PIO requirements. The CS5535 is pretty clean about all this -+ */ -+ -+static void cs5535_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u16 pio_timings[5] = { -+ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 -+ }; -+ static u16 pio_cmd_timings[5] = { -+ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 -+ }; -+ u32 reg, dummy; -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ -+ int mode = adev->pio_mode - XFER_PIO_0; -+ int cmdmode = mode; -+ -+ /* Command timing has to be for the lowest of the pair of devices */ -+ if (pair) { -+ int pairmode = pair->pio_mode - XFER_PIO_0; -+ cmdmode = min(mode, pairmode); -+ /* Write the other drive timing register if it changed */ -+ if (cmdmode < pairmode) -+ wrmsr(ATAC_CH0D0_PIO + 2 * pair->devno, -+ pio_cmd_timings[cmdmode] << 16 | pio_timings[pairmode], 0); -+ } -+ /* Write the drive timing register */ -+ wrmsr(ATAC_CH0D0_PIO + 2 * adev->devno, -+ pio_cmd_timings[cmdmode] << 16 | pio_timings[mode], 0); -+ -+ /* Set the PIO "format 1" bit in the DMA timing register */ -+ rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy); -+ wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg | 0x80000000UL, 0); -+} -+ -+/** -+ * cs5535_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ */ -+ -+static void cs5535_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u32 udma_timings[5] = { 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 }; -+ static u32 mwdma_timings[3] = { 0x7F0FFFF3, 0x7F035352, 0x7F024241 }; -+ u32 reg, dummy; -+ int mode = adev->dma_mode; -+ -+ rdmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, dummy); -+ reg &= 0x80000000UL; -+ if (mode >= XFER_UDMA_0) -+ reg |= udma_timings[mode - XFER_UDMA_0]; -+ else -+ reg |= mwdma_timings[mode - XFER_MW_DMA_0]; -+ wrmsr(ATAC_CH0D0_DMA + 2 * adev->devno, reg, 0); -+} -+ -+static struct scsi_host_template cs5535_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations cs5535_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cs5535_set_piomode, -+ .set_dmamode = cs5535_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = cs5535_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * cs5535_init_one - Initialise a CS5530 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Install a driver for the newly found CS5530 companion chip. Most of -+ * this is just housekeeping. We have to set the chip up correctly and -+ * turn off various bits of emulation magic. -+ */ -+ -+static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &cs5535_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, -+ .port_ops = &cs5535_port_ops -+ }; -+ struct ata_port_info *ports[1] = { &info }; -+ -+ u32 timings, dummy; -+ -+ /* Check the BIOS set the initial timing clock. If not set the -+ timings for PIO0 */ -+ rdmsr(ATAC_CH0D0_PIO, timings, dummy); -+ if (CS5535_BAD_PIO(timings)) -+ wrmsr(ATAC_CH0D0_PIO, 0xF7F4F7F4UL, 0); -+ rdmsr(ATAC_CH0D1_PIO, timings, dummy); -+ if (CS5535_BAD_PIO(timings)) -+ wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); -+ return ata_pci_init_one(dev, ports, 1); -+} -+ -+static struct pci_device_id cs5535[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_NS, 0x002D), }, -+ { 0, }, -+}; -+ -+static struct pci_driver cs5535_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = cs5535, -+ .probe = cs5535_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init cs5535_init(void) -+{ -+ return pci_register_driver(&cs5535_pci_driver); -+} -+ -+ -+static void __exit cs5535_exit(void) -+{ -+ pci_unregister_driver(&cs5535_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox, Jens Altmann, Wolfgan Zuleger, Alexander Kiausch"); -+MODULE_DESCRIPTION("low-level driver for the NS/AMD 5530"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, cs5535); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cs5535_init); -+module_exit(cs5535_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cypress.c linux-2.6.16-rc6/drivers/scsi/pata_cypress.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_cypress.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_cypress.c 2006-02-16 15:37:46.000000000 +0000 -@@ -0,0 +1,215 @@ -+/* -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_cypress" -+#define DRV_VERSION "0.1" -+ -+/* here are the offset definitions for the registers */ -+ -+enum { -+ CY82_IDE_CMDREG = 0x04, -+ CY82_IDE_ADDRSETUP = 0x48, -+ CY82_IDE_MASTER_IOR = 0x4C, -+ CY82_IDE_MASTER_IOW = 0x4D, -+ CY82_IDE_SLAVE_IOR = 0x4E, -+ CY82_IDE_SLAVE_IOW = 0x4F, -+ CY82_IDE_MASTER_8BIT = 0x50, -+ CY82_IDE_SLAVE_8BIT = 0x51, -+ -+ CY82_INDEX_PORT = 0x22, -+ CY82_DATA_PORT = 0x23, -+ -+ CY82_INDEX_CTRLREG1 = 0x01, -+ CY82_INDEX_CHANNEL0 = 0x30, -+ CY82_INDEX_CHANNEL1 = 0x31, -+ CY82_INDEX_TIMEOUT = 0x32 -+}; -+ -+/* Phee Phy Pho Phum */ -+ -+static void cy82c693_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * cy82c693_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. -+ */ -+ -+static void cy82c693_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct ata_timing t; -+ const unsigned long T = 1000000 / 33; -+ short time_16, time_8; -+ u32 addr; -+ -+ if (ata_timing_compute(adev, adev->pio_mode, &t, T, 1) < 0) { -+ printk(KERN_ERR DRV_NAME ": mome computation failed.\n"); -+ return; -+ } -+ -+ time_16 = FIT(t.recover, 0, 15) | (FIT(t.active, 0, 15) << 4); -+ time_8 = FIT(t.act8b, 0, 15) | (FIT(t.rec8b, 0, 15) << 4); -+ -+ if (adev->devno == 0) { -+ pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr); -+ -+ addr &= ~0x0F; /* Mask bits */ -+ addr |= FIT(t.setup, 0, 15); -+ -+ pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr); -+ pci_write_config_byte(pdev, CY82_IDE_MASTER_IOR, time_16); -+ pci_write_config_byte(pdev, CY82_IDE_MASTER_IOW, time_16); -+ pci_write_config_byte(pdev, CY82_IDE_MASTER_8BIT, time_8); -+ } else { -+ pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr); -+ -+ addr &= ~0xF0; /* Mask bits */ -+ addr |= (FIT(t.setup, 0, 15) << 4); -+ -+ pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr); -+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOR, time_16); -+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOW, time_16); -+ pci_write_config_byte(pdev, CY82_IDE_SLAVE_8BIT, time_8); -+ } -+} -+ -+/** -+ * cy82c693_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the DMA mode setup. -+ */ -+ -+static void cy82c693_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ int reg = CY82_INDEX_CHANNEL0 + ap->hard_port_no; -+ -+ /* Be afraid, be very afraid. Magic registers in low I/O space */ -+ outb(reg, 0x22); -+ outb(adev->dma_mode - XFER_MW_DMA_0, 0x23); -+ -+ /* 0x50 gives the best behaviour on the Alpha's using this chip */ -+ outb(CY82_INDEX_TIMEOUT, 0x22); -+ outb(0x50, 0x23); -+} -+ -+static struct scsi_host_template cy82c693_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations cy82c693_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = cy82c693_set_piomode, -+ .set_dmamode = cy82c693_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = cy82c693_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &cy82c693_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &cy82c693_port_ops -+ }; -+ static struct ata_port_info *port_info[1] = { &info }; -+ -+ /* Devfn 1 is the ATA primary. The secondary is magic and on devfn2. For the -+ moment we don't handle the secondary. FIXME */ -+ -+ if (PCI_FUNC(pdev->devfn) != 1) -+ return -ENODEV; -+ -+ return ata_pci_init_one(pdev, port_info, 1); -+} -+ -+static struct pci_device_id cy82c693[] = { -+ { PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0, }, -+}; -+ -+static struct pci_driver cy82c693_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = cy82c693, -+ .probe = cy82c693_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init cy82c693_init(void) -+{ -+ return pci_register_driver(&cy82c693_pci_driver); -+} -+ -+ -+static void __exit cy82c693_exit(void) -+{ -+ pci_unregister_driver(&cy82c693_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the CY82C693 PATA controller"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, cy82c693); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cy82c693_init); -+module_exit(cy82c693_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_efar.c linux-2.6.16-rc6/drivers/scsi/pata_efar.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_efar.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_efar.c 2006-02-16 15:37:53.000000000 +0000 -@@ -0,0 +1,341 @@ -+/* -+ * pata_efar.c - EFAR PIIX clone controller driver -+ * -+ * (C) 2005 Red Hat <alan@redhat.com> -+ * -+ * Some parts based on ata_piix.c by Jeff Garzik and others. -+ * -+ * The EFAR is a PIIX4 clone with UDMA66 support. Unlike the later -+ * Intel ICH controllers the EFAR widened the UDMA mode register bits -+ * and doesn't require the funky clock selection. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_efar" -+#define DRV_VERSION "0.1" -+ -+/** -+ * efar_cable_detect - check for 40/80 pin -+ * @ap: Port -+ * -+ * Perform cable detection for the EFAR ATA interface. This is -+ * different to the PIIX arrangement -+ */ -+ -+static int efar_cable_detect(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 tmp; -+ -+ pci_read_config_byte(pdev, 0x47, &tmp); -+ if (tmp & (2 >> ap->hard_port_no)) -+ return ATA_CBL_PATA40; -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * efar_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void efar_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ const struct pci_bits efar_enable_bits[] = { -+ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ -+ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &efar_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = efar_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * efar_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set PIO mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio = adev->pio_mode - XFER_PIO_0; -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ unsigned int idetm_port= ap->hard_port_no ? 0x42 : 0x40; -+ u16 idetm_data; -+ int control = 0; -+ -+ /* -+ * See Intel Document 298600-004 for the timing programing rules -+ * for PIIX/ICH. The EFAR is a clone so very similar -+ */ -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; -+ -+ if (pio > 2) -+ control |= 1; /* TIME1 enable */ -+ if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ -+ control |= 2; /* IE enable */ -+ /* Intel specifies that the PPE functionality is for disk only */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable */ -+ -+ pci_read_config_word(dev, idetm_port, &idetm_data); -+ -+ /* Enable PPE, IE and TIME as appropriate */ -+ -+ if (adev->devno == 0) { -+ idetm_data &= 0xCCF0; -+ idetm_data |= control; -+ idetm_data |= (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ } else { -+ int shift = 4 * ap->hard_port_no; -+ u8 slave_data; -+ -+ idetm_data &= 0xCC0F; -+ idetm_data |= (control << 4); -+ -+ /* Slave timing in seperate register */ -+ pci_read_config_byte(dev, 0x44, &slave_data); -+ slave_data &= 0x0F << shift; -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift; -+ pci_write_config_byte(dev, 0x44, slave_data); -+ } -+ -+ idetm_data |= 0x4000; /* Ensure SITRE is enabled */ -+ pci_write_config_word(dev, idetm_port, idetm_data); -+} -+ -+/** -+ * efar_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ u8 master_port = ap->hard_port_no ? 0x42 : 0x40; -+ u16 master_data; -+ u8 speed = adev->dma_mode; -+ int devid = adev->devno + 2 * ap->hard_port_no; -+ u8 udma_enable; -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; -+ -+ pci_read_config_word(dev, master_port, &master_data); -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ -+ if (speed >= XFER_UDMA_0) { -+ unsigned int udma = adev->dma_mode - XFER_UDMA_0; -+ u16 udma_timing; -+ -+ udma_enable |= (1 << devid); -+ -+ /* Load the UDMA mode number */ -+ pci_read_config_word(dev, 0x4A, &udma_timing); -+ udma_timing &= ~(7 << (4 * devid)); -+ udma_timing |= udma << (4 * devid); -+ pci_write_config_word(dev, 0x4A, udma_timing); -+ } else { -+ /* -+ * MWDMA is driven by the PIO timings. We must also enable -+ * IORDY unconditionally along with TIME1. PPE has already -+ * been set when the PIO timing was set. -+ */ -+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; -+ unsigned int control; -+ u8 slave_data; -+ const unsigned int needed_pio[3] = { -+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 -+ }; -+ int pio = needed_pio[mwdma] - XFER_PIO_0; -+ -+ control = 3; /* IORDY|TIME1 */ -+ -+ /* If the drive MWDMA is faster than it can do PIO then -+ we must force PIO into PIO0 */ -+ -+ if (adev->pio_mode < needed_pio[mwdma]) -+ /* Enable DMA timing only */ -+ control |= 8; /* PIO cycles in PIO0 */ -+ -+ if (adev->devno) { /* Slave */ -+ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ -+ master_data |= control << 4; -+ pci_read_config_byte(dev, 0x44, &slave_data); -+ slave_data &= (0x0F + 0xE1 * ap->hard_port_no); -+ /* Load the matching timing */ -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->hard_port_no ? 4 : 0); -+ pci_write_config_byte(dev, 0x44, slave_data); -+ } else { /* Master */ -+ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY -+ and master timing bits */ -+ master_data |= control; -+ master_data |= -+ (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ } -+ udma_enable &= ~(1 << devid); -+ pci_write_config_word(dev, master_port, master_data); -+ } -+ pci_write_config_byte(dev, 0x48, udma_enable); -+} -+ -+static struct scsi_host_template efar_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations efar_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = efar_set_piomode, -+ .set_dmamode = efar_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = efar_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+ -+/** -+ * efar_init_one - Register EFAR ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in efar_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ static struct ata_port_info info = { -+ .sht = &efar_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma1-2 */ -+ .udma_mask = 0x0f, /* UDMA 66 */ -+ .port_ops = &efar_ops, -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id efar_pci_tbl[] = { -+ { 0x1055, 0x9130, PCI_ANY_ID, PCI_ANY_ID, }, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver efar_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = efar_pci_tbl, -+ .probe = efar_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init efar_init(void) -+{ -+ return pci_register_driver(&efar_pci_driver); -+} -+ -+static void __exit efar_exit(void) -+{ -+ pci_unregister_driver(&efar_pci_driver); -+} -+ -+ -+module_init(efar_init); -+module_exit(efar_exit); -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("SCSI low-level driver for EFAR PIIX clones"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, efar_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt34x.c linux-2.6.16-rc6/drivers/scsi/pata_hpt34x.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt34x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_hpt34x.c 2006-03-10 17:05:51.000000000 +0000 -@@ -0,0 +1,206 @@ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "hpt34x" -+#define DRV_VERSION "0.1.1" -+ -+/** -+ * hpt34x_bus_reset - reset the hpt34x bus -+ * @ap: ATA port to reset -+ * -+ * Perform the housekeeping when doing an ATA bus reeset. We just -+ * need to force the cable type. -+ */ -+ -+static void hpt34x_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * hpt34x_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Set our PIO requirements. This is fairly simple on the HPT34x as -+ * all we have to do is clear the MWDMA and UDMA bits then load the -+ * mode number. -+ */ -+ -+static void hpt34x_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 r1, r2; -+ int dn = 2 * ap->hard_port_no + adev->devno; -+ -+ pci_read_config_dword(pdev, 0x44, &r1); -+ pci_read_config_dword(pdev, 0x48, &r2); -+ /* Load the PIO timing number */ -+ r1 &= ~(7 << (3 * dn)); -+ r1 |= (adev->pio_mode - XFER_PIO_0) << (3 * dn); -+ r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ -+ -+ pci_write_config_dword(pdev, 0x44, r1); -+ pci_write_config_dword(pdev, 0x48, r2); -+} -+ -+/** -+ * hpt34x_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * Set up the channel for MWDMA or UDMA modes. Much the same as with -+ * PIO, load the mode number and then set MWDMA or UDMA flag. -+ */ -+ -+static void hpt34x_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 r1, r2; -+ int dn = 2 * ap->hard_port_no + adev->devno; -+ int mode_num = adev->dma_mode & 0x0F; -+ -+ pci_read_config_dword(pdev, 0x44, &r1); -+ pci_read_config_dword(pdev, 0x48, &r2); -+ /* Load the timing number */ -+ r1 &= ~(7 << (3 * dn)); -+ r1 |= (mode_num << (3 * dn)); -+ r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ -+ -+ if (adev->dma_mode >= XFER_UDMA_0) -+ r2 |= 0x01 << dn; /* Ultra mode */ -+ else -+ r2 |= 0x10 << dn; /* MWDMA */ -+ -+ pci_write_config_dword(pdev, 0x44, r1); -+ pci_write_config_dword(pdev, 0x48, r2); -+} -+ -+static struct scsi_host_template hpt34x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations hpt34x_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt34x_set_piomode, -+ .set_dmamode = hpt34x_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt34x_phy_reset, -+ -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * hpt34x_init_one - Initialise an HPT343/363 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Perform basic initialisation. The chip has a quirk that it won't -+ * function unless it is at XX00. The old ATA driver touched this up -+ * but we leave it for pci quirks to do properly. -+ */ -+ -+static int hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &hpt34x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x07, -+ .port_ops = &hpt34x_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ u16 cmd; -+ -+ /* Initialize the board */ -+ pci_write_config_word(dev, 0x80, 0x00); -+ /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ if (cmd & PCI_COMMAND_MEMORY) -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); -+ else -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); -+ -+ /* Now kick off ATA set up */ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id hpt34x[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343), }, -+ { 0, }, -+}; -+ -+static struct pci_driver hpt34x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = hpt34x, -+ .probe = hpt34x_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init hpt34x_init(void) -+{ -+ return pci_register_driver(&hpt34x_pci_driver); -+} -+ -+ -+static void __exit hpt34x_exit(void) -+{ -+ pci_unregister_driver(&hpt34x_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT343/363"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, hpt34x); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(hpt34x_init); -+module_exit(hpt34x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt366.c linux-2.6.16-rc6/drivers/scsi/pata_hpt366.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt366.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_hpt366.c 2006-03-10 17:06:06.000000000 +0000 -@@ -0,0 +1,479 @@ -+/* -+ * Libata driver for the highpoint 366 and 368 UDMA66 ATA controllers. -+ * -+ * This driver is heavily based upon: -+ * -+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 -+ * -+ * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> -+ * Portions Copyright (C) 2001 Sun Microsystems, Inc. -+ * Portions Copyright (C) 2003 Red Hat Inc -+ * -+ * -+ * TODO -+ * Maybe PLL mode -+ * Look into engine reset on timeout errors. Should not be -+ * required. -+ */ -+ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "hpt36x" -+#define DRV_VERSION "0.2.1" -+ -+struct hpt_clock { -+ u8 xfer_speed; -+ u32 timing; -+}; -+ -+/* key for bus clock timings -+ * bit -+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file -+ * register access. -+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file -+ * register access. -+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. -+ * during task file register access. -+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA -+ * xfer. -+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task -+ * register access. -+ * 28 UDMA enable -+ * 29 DMA enable -+ * 30 PIO_MST enable. if set, the chip is in bus master mode during -+ * PIO. -+ * 31 FIFO enable. -+ */ -+ -+static struct chipset_bus_clock_list_entry hpt366_40[] = { -+ { XFER_UDMA_4, 0x900fd943 }, -+ { XFER_UDMA_3, 0x900ad943 }, -+ { XFER_UDMA_2, 0x900bd943 }, -+ { XFER_UDMA_1, 0x9008d943 }, -+ { XFER_UDMA_0, 0x9008d943 }, -+ -+ { XFER_MW_DMA_2, 0xa008d943 }, -+ { XFER_MW_DMA_1, 0xa010d955 }, -+ { XFER_MW_DMA_0, 0xa010d9fc }, -+ -+ { XFER_PIO_4, 0xc008d963 }, -+ { XFER_PIO_3, 0xc010d974 }, -+ { XFER_PIO_2, 0xc010d997 }, -+ { XFER_PIO_1, 0xc010d9c7 }, -+ { XFER_PIO_0, 0xc018d9d9 }, -+ { 0, 0x0120d9d9 } -+}; -+ -+static struct chipset_bus_clock_list_entry hpt366_33[] = { -+ { XFER_UDMA_4, 0x90c9a731 }, -+ { XFER_UDMA_3, 0x90cfa731 }, -+ { XFER_UDMA_2, 0x90caa731 }, -+ { XFER_UDMA_1, 0x90cba731 }, -+ { XFER_UDMA_0, 0x90c8a731 }, -+ -+ { XFER_MW_DMA_2, 0xa0c8a731 }, -+ { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ -+ { XFER_MW_DMA_0, 0xa0c8a797 }, -+ -+ { XFER_PIO_4, 0xc0c8a731 }, -+ { XFER_PIO_3, 0xc0c8a742 }, -+ { XFER_PIO_2, 0xc0d0a753 }, -+ { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ -+ { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ -+ { 0, 0x0120a7a7 } -+}; -+ -+static struct chipset_bus_clock_list_entry hpt366_25[] = { -+ { XFER_UDMA_4, 0x90c98521 }, -+ { XFER_UDMA_3, 0x90cf8521 }, -+ { XFER_UDMA_2, 0x90cf8521 }, -+ { XFER_UDMA_1, 0x90cb8521 }, -+ { XFER_UDMA_0, 0x90cb8521 }, -+ -+ { XFER_MW_DMA_2, 0xa0ca8521 }, -+ { XFER_MW_DMA_1, 0xa0ca8532 }, -+ { XFER_MW_DMA_0, 0xa0ca8575 }, -+ -+ { XFER_PIO_4, 0xc0ca8521 }, -+ { XFER_PIO_3, 0xc0ca8532 }, -+ { XFER_PIO_2, 0xc0ca8542 }, -+ { XFER_PIO_1, 0xc0d08572 }, -+ { XFER_PIO_0, 0xc0d08585 }, -+ { 0, 0x01208585 } -+}; -+ -+static const char *bad_ata33[] = { -+ "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", -+ "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", -+ "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", -+ "Maxtor 90510D4", -+ "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", -+ "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", -+ "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", -+ NULL -+}; -+ -+static const char *bad_ata66_4[] = { -+ "IBM-DTLA-307075", -+ "IBM-DTLA-307060", -+ "IBM-DTLA-307045", -+ "IBM-DTLA-307030", -+ "IBM-DTLA-307020", -+ "IBM-DTLA-307015", -+ "IBM-DTLA-305040", -+ "IBM-DTLA-305030", -+ "IBM-DTLA-305020", -+ "IC35L010AVER07-0", -+ "IC35L020AVER07-0", -+ "IC35L030AVER07-0", -+ "IC35L040AVER07-0", -+ "IC35L060AVER07-0", -+ "WDC AC310200R", -+ NULL -+}; -+ -+static const char *bad_ata66_3[] = { -+ "WDC AC310200R", -+ NULL -+}; -+ -+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) -+{ -+ unsigned char model_num[40]; -+ char *s; -+ unsigned int len; -+ int i = 0; -+ -+ ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, -+ sizeof(model_num)); -+ s = &model_num[0]; -+ len = strnlen(s, sizeof(model_num)); -+ -+ /* ATAPI specifies that empty space is blank-filled; remove blanks */ -+ while ((len > 0) && (s[len - 1] == ' ')) { -+ len--; -+ s[len] = 0; -+ } -+ -+ while(list[i] != NULL) { -+ if (!strncmp(list[i], s, len)) { -+ printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", -+ modestr, list[i]); -+ return 1; -+ } -+ i++; -+ } -+ return 0; -+} -+ -+/** -+ * hpt366_filter - mode selection filter -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Block UDMA on devices that cause trouble with this controller. -+ */ -+ -+static unsigned int hpt366_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ if (adev->class != ATA_DEV_ATA) -+ return mask; -+ if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) -+ return 0; -+ if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3)) -+ return mask & 0x07; -+ if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) -+ return mask & 0x0F; -+ return mask; -+} -+ -+/** -+ * hpt36x_find_mode - reset the hpt36x bus -+ * @ap: ATA port -+ * @speed: transfer mode -+ * -+ * Return the 32bit register programming information for this channel -+ * that matches the speed provided. -+ */ -+ -+static u32 hpt36x_find_mode(struct ata_port *ap, int speed) -+{ -+ struct hpt_clock *clocks = ap->host_set->private_data; -+ -+ while(clocks->xfer_speed) { -+ if (clocks->xfer_speed == speed) -+ return clocks->timing; -+ clocks++; -+ } -+ BUG(); -+} -+ -+/** -+ * hpt36x_phy_reset - reset the hpt36x bus -+ * @ap: ATA port to reset -+ * -+ * Perform the PHY reset handling for the 366/368 -+ */ -+ -+static void hpt36x_phy_reset(struct ata_port *ap) -+{ -+ u8 scr2, ata66; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_byte(pdev, 0x5A, &ata66); -+ if (ata66 & (1 << ap->hard_port_no)) -+ ap->cbl = ATA_CBL_PATA40; -+ else -+ ap->cbl = ATA_CBL_PATA80; -+ -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * hpt366_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Perform PIO mode setup. -+ */ -+ -+static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ if (fast & 0x80) { -+ fast &= ~0x80; -+ pci_write_config_byte(pdev, addr2, fast); -+ } -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt36x_find_mode(ap, adev->pio_mode); -+ mode &= ~0x8000000; /* No FIFO in PIO */ -+ mode &= ~0x30070000; /* Leave config bits alone */ -+ reg &= 0x30070000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt366_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * Set up the channel for MWDMA or UDMA modes. Much the same as with -+ * PIO, load the mode number and then set MWDMA or UDMA flag. -+ */ -+ -+static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ if (fast & 0x80) { -+ fast &= ~0x80; -+ pci_write_config_byte(pdev, addr2, fast); -+ } -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt36x_find_mode(ap, adev->dma_mode); -+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ -+ mode &= ~0xC0000000; /* Leave config bits alone */ -+ reg &= 0xC0000000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+static struct scsi_host_template hpt36x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+/* -+ * Configuration for HPT366/68 -+ */ -+ -+static struct ata_port_operations hpt366_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt366_set_piomode, -+ .set_dmamode = hpt366_set_dmamode, -+ .mode_filter = hpt366_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt36x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * hpt36x_init_one - Initialise an HPT366/368 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Initialise an HPT36x device. There are some interesting complications -+ * here. Firstly the chip may report 366 and be one of several variants. -+ * Secondly all the timings depend on the clock for the chip which we must -+ * detect and look up -+ * -+ * This is the known chip mappings. It may be missing a couple of later -+ * releases. -+ * -+ * Chip version PCI Rev Notes -+ * HPT366 4 (HPT366) 0 UDMA66 -+ * HPT366 4 (HPT366) 1 UDMA66 -+ * HPT368 4 (HPT366) 2 UDMA66 -+ * HPT37x/30x 4 (HPT366) 3+ Other driver -+ * -+ */ -+ -+static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info_hpt366 = { -+ .sht = &hpt366_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, -+ .port_ops = &hpt370_port_ops -+ }; -+ struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366}; -+ -+ u8 irqmask; -+ u32 class_rev; -+ u32 reg1; -+ -+ struct hpt_chip *chip_table; -+ int clock_slot; -+ -+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); -+ class_rev &= 0xFF; -+ -+ /* May be a later chip in disguise. Check */ -+ /* Newer chips are in the HPT36x driver. Ignore them */ -+ if (class_rev > 2) -+ return -ENODEV; -+ -+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); -+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); -+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); -+ -+ pci_read_config_byte(dev, 0x51, &drive_fast); -+ if (drive_fast & 0x80) -+ pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); -+ -+ pci_read_config_dword(dev, 0x40, ®1); -+ -+ /* PCI clocking determines the ATA timing values to use */ -+ switch((reg1 & 0x700) { -+ case 5: -+ port->private_data = hpt366_40; -+ break; -+ case 9: -+ port->private_data = hpt366_25; -+ break; -+ default: -+ port->private_data = hpt366_33; -+ break; -+ } -+ port_info[0] = port_info[1] = port; -+ /* Now kick off ATA set up */ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id hpt36x[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, -+ { 0, }, -+}; -+ -+static struct pci_driver hpt36x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = hpt36x, -+ .probe = hpt36x_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init hpt36x_init(void) -+{ -+ return pci_register_driver(&hpt36x_pci_driver); -+} -+ -+ -+static void __exit hpt36x_exit(void) -+{ -+ pci_unregister_driver(&hpt36x_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, hpt36x); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(hpt36x_init); -+module_exit(hpt36x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt37x.c linux-2.6.16-rc6/drivers/scsi/pata_hpt37x.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt37x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_hpt37x.c 2006-03-10 17:03:35.000000000 +0000 -@@ -0,0 +1,1233 @@ -+/* -+ * Libata driver for the highpoint 37x and 30x UDMA66 ATA controllers. -+ * -+ * This driver is heavily based upon: -+ * -+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 -+ * -+ * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> -+ * Portions Copyright (C) 2001 Sun Microsystems, Inc. -+ * Portions Copyright (C) 2003 Red Hat Inc -+ * -+ * TODO -+ * PLL mode -+ * Look into engine reset on timeout errors. Should not be -+ * required. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "hpt37x" -+#define DRV_VERSION "0.2.2" -+ -+struct hpt_clock { -+ u8 xfer_speed; -+ u32 timing; -+}; -+ -+struct hpt_chip { -+ const char *name; -+ unsigned int base; -+ struct hpt_clock *clocks[4]; -+}; -+ -+/* key for bus clock timings -+ * bit -+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file -+ * register access. -+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file -+ * register access. -+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. -+ * during task file register access. -+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA -+ * xfer. -+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task -+ * register access. -+ * 28 UDMA enable -+ * 29 DMA enable -+ * 30 PIO_MST enable. if set, the chip is in bus master mode during -+ * PIO. -+ * 31 FIFO enable. -+ */ -+ -+/* from highpoint documentation. these are old values */ -+static struct hpt_clock hpt370_timings_33[] = { -+/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ -+ { XFER_UDMA_5, 0x16454e31 }, -+ { XFER_UDMA_4, 0x16454e31 }, -+ { XFER_UDMA_3, 0x166d4e31 }, -+ { XFER_UDMA_2, 0x16494e31 }, -+ { XFER_UDMA_1, 0x164d4e31 }, -+ { XFER_UDMA_0, 0x16514e31 }, -+ -+ { XFER_MW_DMA_2, 0x26514e21 }, -+ { XFER_MW_DMA_1, 0x26514e33 }, -+ { XFER_MW_DMA_0, 0x26514e97 }, -+ -+ { XFER_PIO_4, 0x06514e21 }, -+ { XFER_PIO_3, 0x06514e22 }, -+ { XFER_PIO_2, 0x06514e33 }, -+ { XFER_PIO_1, 0x06914e43 }, -+ { XFER_PIO_0, 0x06914e57 }, -+ { 0, 0x06514e57 } -+}; -+ -+static struct hpt_clock hpt370_timings_66[] = { -+ { XFER_UDMA_5, 0x14846231 }, -+ { XFER_UDMA_4, 0x14886231 }, -+ { XFER_UDMA_3, 0x148c6231 }, -+ { XFER_UDMA_2, 0x148c6231 }, -+ { XFER_UDMA_1, 0x14906231 }, -+ { XFER_UDMA_0, 0x14986231 }, -+ -+ { XFER_MW_DMA_2, 0x26514e21 }, -+ { XFER_MW_DMA_1, 0x26514e33 }, -+ { XFER_MW_DMA_0, 0x26514e97 }, -+ -+ { XFER_PIO_4, 0x06514e21 }, -+ { XFER_PIO_3, 0x06514e22 }, -+ { XFER_PIO_2, 0x06514e33 }, -+ { XFER_PIO_1, 0x06914e43 }, -+ { XFER_PIO_0, 0x06914e57 }, -+ { 0, 0x06514e57 } -+}; -+ -+/* these are the current (4 sep 2001) timings from highpoint */ -+static struct hpt_clock hpt370a_timings_33[] = { -+ { XFER_UDMA_5, 0x12446231 }, -+ { XFER_UDMA_4, 0x12446231 }, -+ { XFER_UDMA_3, 0x126c6231 }, -+ { XFER_UDMA_2, 0x12486231 }, -+ { XFER_UDMA_1, 0x124c6233 }, -+ { XFER_UDMA_0, 0x12506297 }, -+ -+ { XFER_MW_DMA_2, 0x22406c31 }, -+ { XFER_MW_DMA_1, 0x22406c33 }, -+ { XFER_MW_DMA_0, 0x22406c97 }, -+ -+ { XFER_PIO_4, 0x06414e31 }, -+ { XFER_PIO_3, 0x06414e42 }, -+ { XFER_PIO_2, 0x06414e53 }, -+ { XFER_PIO_1, 0x06814e93 }, -+ { XFER_PIO_0, 0x06814ea7 }, -+ { 0, 0x06814ea7 } -+}; -+ -+/* 2x 33MHz timings */ -+static struct hpt_clock hpt370a_timings_66[] = { -+ { XFER_UDMA_5, 0x1488e673 }, -+ { XFER_UDMA_4, 0x1488e673 }, -+ { XFER_UDMA_3, 0x1498e673 }, -+ { XFER_UDMA_2, 0x1490e673 }, -+ { XFER_UDMA_1, 0x1498e677 }, -+ { XFER_UDMA_0, 0x14a0e73f }, -+ -+ { XFER_MW_DMA_2, 0x2480fa73 }, -+ { XFER_MW_DMA_1, 0x2480fa77 }, -+ { XFER_MW_DMA_0, 0x2480fb3f }, -+ -+ { XFER_PIO_4, 0x0c82be73 }, -+ { XFER_PIO_3, 0x0c82be95 }, -+ { XFER_PIO_2, 0x0c82beb7 }, -+ { XFER_PIO_1, 0x0d02bf37 }, -+ { XFER_PIO_0, 0x0d02bf5f }, -+ { 0, 0x0d02bf5f } -+}; -+ -+static struct hpt_clock hpt370a_timings_50[] = { -+ { XFER_UDMA_5, 0x12848242 }, -+ { XFER_UDMA_4, 0x12ac8242 }, -+ { XFER_UDMA_3, 0x128c8242 }, -+ { XFER_UDMA_2, 0x120c8242 }, -+ { XFER_UDMA_1, 0x12148254 }, -+ { XFER_UDMA_0, 0x121882ea }, -+ -+ { XFER_MW_DMA_2, 0x22808242 }, -+ { XFER_MW_DMA_1, 0x22808254 }, -+ { XFER_MW_DMA_0, 0x228082ea }, -+ -+ { XFER_PIO_4, 0x0a81f442 }, -+ { XFER_PIO_3, 0x0a81f443 }, -+ { XFER_PIO_2, 0x0a81f454 }, -+ { XFER_PIO_1, 0x0ac1f465 }, -+ { XFER_PIO_0, 0x0ac1f48a }, -+ { 0, 0x0ac1f48a } -+}; -+ -+static struct hpt_clock hpt372_timings_33[] = { -+ { XFER_UDMA_6, 0x1c81dc62 }, -+ { XFER_UDMA_5, 0x1c6ddc62 }, -+ { XFER_UDMA_4, 0x1c8ddc62 }, -+ { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ -+ { XFER_UDMA_2, 0x1c91dc62 }, -+ { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ -+ { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ -+ -+ { XFER_MW_DMA_2, 0x2c829262 }, -+ { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ -+ { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ -+ -+ { XFER_PIO_4, 0x0c829c62 }, -+ { XFER_PIO_3, 0x0c829c84 }, -+ { XFER_PIO_2, 0x0c829ca6 }, -+ { XFER_PIO_1, 0x0d029d26 }, -+ { XFER_PIO_0, 0x0d029d5e }, -+ { 0, 0x0d029d5e } -+}; -+ -+static struct hpt_clock hpt372_timings_50[] = { -+ { XFER_UDMA_5, 0x12848242 }, -+ { XFER_UDMA_4, 0x12ac8242 }, -+ { XFER_UDMA_3, 0x128c8242 }, -+ { XFER_UDMA_2, 0x120c8242 }, -+ { XFER_UDMA_1, 0x12148254 }, -+ { XFER_UDMA_0, 0x121882ea }, -+ -+ { XFER_MW_DMA_2, 0x22808242 }, -+ { XFER_MW_DMA_1, 0x22808254 }, -+ { XFER_MW_DMA_0, 0x228082ea }, -+ -+ { XFER_PIO_4, 0x0a81f442 }, -+ { XFER_PIO_3, 0x0a81f443 }, -+ { XFER_PIO_2, 0x0a81f454 }, -+ { XFER_PIO_1, 0x0ac1f465 }, -+ { XFER_PIO_0, 0x0ac1f48a }, -+ { 0, 0x0a81f443 } -+}; -+ -+static struct hpt_clock hpt372_timings_66[] = { -+ { XFER_UDMA_6, 0x1c869c62 }, -+ { XFER_UDMA_5, 0x1cae9c62 }, -+ { XFER_UDMA_4, 0x1c8a9c62 }, -+ { XFER_UDMA_3, 0x1c8e9c62 }, -+ { XFER_UDMA_2, 0x1c929c62 }, -+ { XFER_UDMA_1, 0x1c9a9c62 }, -+ { XFER_UDMA_0, 0x1c829c62 }, -+ -+ { XFER_MW_DMA_2, 0x2c829c62 }, -+ { XFER_MW_DMA_1, 0x2c829c66 }, -+ { XFER_MW_DMA_0, 0x2c829d2e }, -+ -+ { XFER_PIO_4, 0x0c829c62 }, -+ { XFER_PIO_3, 0x0c829c84 }, -+ { XFER_PIO_2, 0x0c829ca6 }, -+ { XFER_PIO_1, 0x0d029d26 }, -+ { XFER_PIO_0, 0x0d029d5e }, -+ { 0, 0x0d029d26 } -+}; -+ -+static struct hpt_clock hpt374_timings_33[] = { -+ { XFER_UDMA_6, 0x12808242 }, -+ { XFER_UDMA_5, 0x12848242 }, -+ { XFER_UDMA_4, 0x12ac8242 }, -+ { XFER_UDMA_3, 0x128c8242 }, -+ { XFER_UDMA_2, 0x120c8242 }, -+ { XFER_UDMA_1, 0x12148254 }, -+ { XFER_UDMA_0, 0x121882ea }, -+ -+ { XFER_MW_DMA_2, 0x22808242 }, -+ { XFER_MW_DMA_1, 0x22808254 }, -+ { XFER_MW_DMA_0, 0x228082ea }, -+ -+ { XFER_PIO_4, 0x0a81f442 }, -+ { XFER_PIO_3, 0x0a81f443 }, -+ { XFER_PIO_2, 0x0a81f454 }, -+ { XFER_PIO_1, 0x0ac1f465 }, -+ { XFER_PIO_0, 0x0ac1f48a }, -+ { 0, 0x06814e93 } -+}; -+ -+static struct hpt_chip hpt370 = { -+ "HPT370", -+ 48, -+ { -+ hpt370_timings_33, -+ NULL, -+ NULL, -+ hpt370_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt370a = { -+ "HPT370A", -+ 48, -+ { -+ hpt370a_timings_33, -+ NULL, -+ hpt370a_timings_50, -+ hpt370a_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt372 = { -+ "HPT372", -+ 55, -+ { -+ hpt372_timings_33, -+ NULL, -+ hpt372_timings_50, -+ hpt372_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt302 = { -+ "HPT302", -+ 66, -+ { -+ hpt372_timings_33, -+ NULL, -+ hpt372_timings_50, -+ hpt372_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt371 = { -+ "HPT371", -+ 66, -+ { -+ hpt372_timings_33, -+ NULL, -+ hpt372_timings_50, -+ hpt372_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt372a = { -+ "HPT372A", -+ 66, -+ { -+ hpt372_timings_33, -+ NULL, -+ hpt372_timings_50, -+ hpt372_timings_66 -+ } -+}; -+ -+static struct hpt_chip hpt374 = { -+ "HPT374", -+ 48, -+ { -+ hpt374_timings_33, -+ NULL, -+ NULL, -+ NULL -+ } -+}; -+ -+/** -+ * hpt37x_find_mode - reset the hpt37x bus -+ * @ap: ATA port -+ * @speed: transfer mode -+ * -+ * Return the 32bit register programming information for this channel -+ * that matches the speed provided. -+ */ -+ -+static u32 hpt37x_find_mode(struct ata_port *ap, int speed) -+{ -+ struct hpt_clock *clocks = ap->host_set->private_data; -+ -+ while(clocks->xfer_speed) { -+ if (clocks->xfer_speed == speed) -+ return clocks->timing; -+ clocks++; -+ } -+ BUG(); -+} -+ -+static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) -+{ -+ unsigned char model_num[40]; -+ char *s; -+ unsigned int len; -+ int i = 0; -+ -+ ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, -+ sizeof(model_num)); -+ s = &model_num[0]; -+ len = strnlen(s, sizeof(model_num)); -+ -+ /* ATAPI specifies that empty space is blank-filled; remove blanks */ -+ while ((len > 0) && (s[len - 1] == ' ')) { -+ len--; -+ s[len] = 0; -+ } -+ -+ while(list[i] != NULL) { -+ if (!strncmp(list[i], s, len)) { -+ printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", -+ modestr, list[i]); -+ return 1; -+ } -+ i++; -+ } -+ return 0; -+} -+ -+static const char *bad_ata33[] = { -+ "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", -+ "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", -+ "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", -+ "Maxtor 90510D4", -+ "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", -+ "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", -+ "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", -+ NULL -+}; -+ -+static const char *bad_ata100_5[] = { -+ "IBM-DTLA-307075", -+ "IBM-DTLA-307060", -+ "IBM-DTLA-307045", -+ "IBM-DTLA-307030", -+ "IBM-DTLA-307020", -+ "IBM-DTLA-307015", -+ "IBM-DTLA-305040", -+ "IBM-DTLA-305030", -+ "IBM-DTLA-305020", -+ "IC35L010AVER07-0", -+ "IC35L020AVER07-0", -+ "IC35L030AVER07-0", -+ "IC35L040AVER07-0", -+ "IC35L060AVER07-0", -+ "WDC AC310200R", -+ NULL -+}; -+ -+/** -+ * hpt370_filter - mode selection filter -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Block UDMA on devices that cause trouble with this controller. -+ */ -+ -+static unsigned int hpt370_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ if (adev->class != ATA_DEV_ATA) -+ return mask; -+ if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) -+ return mask & 0x1F; -+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) -+ return mask & 0x1F; -+ return mask; -+} -+ -+/** -+ * hpt370a_filter - mode selection filter -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Block UDMA on devices that cause trouble with this controller. -+ */ -+ -+static unsigned int hpt370a_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ if (adev->class != ATA_DEV_ATA) -+ return mask; -+ if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) -+ return mask & 0x1F; -+ return mask; -+} -+ -+/** -+ * hpt37x_phy_reset - reset the hpt37x bus -+ * @ap: ATA port to reset -+ * -+ * Perform the PHY reset handling for the 370/372 and 374 func 0 -+ */ -+ -+static void hpt37x_phy_reset(struct ata_port *ap) -+{ -+ u8 scr2, ata66; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_byte(pdev, 0x5B, &scr2); -+ pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); -+ /* Cable register now active */ -+ pci_read_config_byte(pdev, 0x5A, &ata66); -+ /* Restore state */ -+ pci_write_config_byte(pdev, 0x5B, scr2); -+ -+ if (ata66 & (1 << ap->hard_port_no)) -+ ap->cbl = ATA_CBL_PATA40; -+ else -+ ap->cbl = ATA_CBL_PATA80; -+ -+ /* Reset the state machine */ -+ pci_write_config_byte(pdev, 0x50, 0x37); -+ pci_write_config_byte(pdev, 0x54, 0x37); -+ udelay(100); -+ -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * hpt374_phy_reset - reset the hpt374 -+ * @ap: ATA port to reset -+ * -+ * The 374 cable detect is a little different due to the extra -+ * channels. The function 0 channels work like usual but function 1 -+ * is special -+ */ -+ -+static void hpt374_phy_reset(struct ata_port *ap) -+{ -+ u16 mcr3, mcr6; -+ u8 ata66; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ if (!(PCI_FUNC(pdev->devfn) & 1)) { -+ hpt37x_phy_reset(ap); -+ return; -+ } -+ /* Do the extra channel work */ -+ pci_read_config_word(pdev, 0x52, &mcr3); -+ pci_read_config_word(pdev, 0x56, &mcr6); -+ /* Set bit 15 of 0x52 to enable TCBLID as input -+ Set bit 15 of 0x56 to enable FCBLID as input -+ */ -+ pci_write_config_word(pdev, 0x52, mcr3 | 0x8000); -+ pci_write_config_word(pdev, 0x56, mcr6 | 0x8000); -+ pci_read_config_byte(pdev, 0x5A, &ata66); -+ /* Reset TCBLID/FCBLID to output */ -+ pci_write_config_word(pdev, 0x52, mcr3); -+ pci_write_config_word(pdev, 0x56, mcr6); -+ -+ if (ata66 & (1 << ap->hard_port_no)) -+ ap->cbl = ATA_CBL_PATA40; -+ else -+ ap->cbl = ATA_CBL_PATA80; -+ -+ /* Reset the state machine */ -+ pci_write_config_byte(pdev, 0x50, 0x37); -+ pci_write_config_byte(pdev, 0x54, 0x37); -+ udelay(100); -+ -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+ -+/** -+ * hpt370_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Perform PIO mode setup. -+ */ -+ -+static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x02; -+ fast |= 0x01; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt37x_find_mode(ap, adev->pio_mode); -+ mode &= ~0x8000000; /* No FIFO in PIO */ -+ mode &= ~0x30070000; /* Leave config bits alone */ -+ reg &= 0x30070000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt370_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * Set up the channel for MWDMA or UDMA modes. Much the same as with -+ * PIO, load the mode number and then set MWDMA or UDMA flag. -+ */ -+ -+static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x02; -+ fast |= 0x01; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt37x_find_mode(ap, adev->dma_mode); -+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ -+ mode &= ~0xC0000000; /* Leave config bits alone */ -+ reg &= 0xC0000000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt370_bmdma_start - DMA engine begin -+ * @qc: ATA command -+ * -+ * The 370 and 370A want us to reset the DMA engine each time we -+ * use it. The 372 and later are fine. -+ */ -+ -+static void hpt370_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ pci_write_config_byte(pdev, 0x50 + 4 * ap->hard_port_no, 0x37); -+ udelay(10); -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * hpt370_bmdma_end - DMA engine stop -+ * @qc: ATA command -+ * -+ * Work around the HPT370 DMA engine. -+ */ -+ -+static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 dma_stat = inb(ap->ioaddr.bmdma_addr + 2); -+ u8 dma_cmd; -+ unsigned long bmdma = ap->ioaddr.bmdma_addr; -+ -+ if (dma_stat & 0x01) { -+ udelay(20); -+ dma_stat = inb(bmdma + 2); -+ } -+ if (dma_stat & 0x01) { -+ /* Clear the engine */ -+ pci_write_config_byte(pdev, 0x50 + 4 * ap->hard_port_no, 0x37); -+ udelay(10); -+ /* Stop DMA */ -+ dma_cmd = inb(bmdma ); -+ outb(dma_cmd & 0xFE, bmdma); -+ /* Clear Error */ -+ dma_stat = inb(bmdma + 2); -+ outb(dma_stat | 0x06 , bmdma + 2); -+ /* Clear the engine */ -+ pci_write_config_byte(pdev, 0x50 + 4 * ap->hard_port_no, 0x37); -+ udelay(10); -+ } -+ ata_bmdma_stop(qc); -+} -+ -+/** -+ * hpt372_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Perform PIO mode setup. -+ */ -+ -+static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x07; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt37x_find_mode(ap, adev->pio_mode); -+ -+ printk("Find mode for %d reports %X\n", adev->pio_mode, mode); -+ mode &= ~0x80000000; /* No FIFO in PIO */ -+ mode &= ~0x30070000; /* Leave config bits alone */ -+ reg &= 0x30070000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt372_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * Set up the channel for MWDMA or UDMA modes. Much the same as with -+ * PIO, load the mode number and then set MWDMA or UDMA flag. -+ */ -+ -+static void hpt372_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x07; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt37x_find_mode(ap, adev->dma_mode); -+ printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); -+ mode &= ~0xC0000000; /* Leave config bits alone */ -+ mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ -+ reg &= 0xC0000000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt37x_bmdma_end - DMA engine stop -+ * @qc: ATA command -+ * -+ * Clean up after the HPT372 and later DMA engine -+ */ -+ -+static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int mscreg = 0x50 + 2 * ap->hard_port_no; -+ u8 bwsr_stat, msc_stat; -+ -+ pci_read_config_byte(pdev, 0x6A, &bwsr_stat); -+ pci_read_config_byte(pdev, mscreg, &msc_stat); -+ if (bwsr_stat & (1 << ap->hard_port_no)) -+ pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); -+ ata_bmdma_stop(qc); -+} -+ -+ -+static struct scsi_host_template hpt37x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+/* -+ * Configuration for HPT370 -+ */ -+ -+static struct ata_port_operations hpt370_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt370_set_piomode, -+ .set_dmamode = hpt370_set_dmamode, -+ .mode_filter = hpt370_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt37x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = hpt370_bmdma_start, -+ .bmdma_stop = hpt370_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Configuration for HPT370A. Close to 370 but less filters -+ */ -+ -+static struct ata_port_operations hpt370a_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt370_set_piomode, -+ .set_dmamode = hpt370_set_dmamode, -+ .mode_filter = hpt370a_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt37x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = hpt370_bmdma_start, -+ .bmdma_stop = hpt370_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Configuration for HPT372, HPT371, HPT302. Slightly different PIO -+ * and DMA mode setting functionality. -+ */ -+ -+static struct ata_port_operations hpt372_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt372_set_piomode, -+ .set_dmamode = hpt372_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt37x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = hpt37x_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Configuration for HPT374. Mode setting works like 372 and friends -+ * but we have a different cable detection procedure. -+ */ -+ -+static struct ata_port_operations hpt374_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt372_set_piomode, -+ .set_dmamode = hpt372_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt374_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = hpt37x_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * htp37x_clock_slot - Turn timing to PC clock entry -+ * @freq: Reported frequency timing -+ * @base: Base timing -+ * -+ * Turn the timing data intoa clock slot (0 for 33, 1 for 40, 2 for 50 -+ * and 3 for 66Mhz) -+ */ -+ -+static int hpt37x_clock_slot(unsigned int freq, unsigned int base) -+{ -+ unsigned int f = (base * freq) / 192; /* Mhz */ -+ if (f < 40) -+ return 0; /* 33Mhz slot */ -+ if (f < 45) -+ return 1; /* 40Mhz slot */ -+ if (f < 55) -+ return 2; /* 50Mhz slot */ -+ return 3; /* 60Mhz slot */ -+} -+ -+/** -+ * hpt37x_calibrate_dpll - Calibrate the DPLL loop -+ * @dev: PCI device -+ * -+ * Perform a calibration cycle on the HPT37x DPLL. Returns 1 if this -+ * succeeds -+ */ -+ -+static int hpt37x_calibrate_dpll(struct pci_dev *dev) -+{ -+ u8 reg5b; -+ u32 reg5c; -+ int tries; -+ -+ for(tries = 0; tries < 0x5000; tries++) { -+ udelay(50); -+ pci_read_config_byte(dev, 0x5b, ®5b); -+ if (reg5b & 0x80) { -+ /* See if it stays set */ -+ for(tries = 0; tries < 0x1000; tries ++) { -+ pci_read_config_byte(dev, 0x5b, ®5b); -+ /* Failed ? */ -+ if ((reg5b & 0x80) == 0) -+ return 0; -+ } -+ /* Turn off tuning, we have the DPLL set */ -+ pci_read_config_dword(dev, 0x5c, ®5c); -+ pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); -+ return 1; -+ } -+ } -+ /* Never went stable */ -+ return 0; -+} -+/** -+ * hpt37x_init_one - Initialise an HPT37X/302 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Initialise an HPT37x device. There are some interesting complications -+ * here. Firstly the chip may report 366 and be one of several variants. -+ * Secondly all the timings depend on the clock for the chip which we must -+ * detect and look up -+ * -+ * This is the known chip mappings. It may be missing a couple of later -+ * releases. -+ * -+ * Chip version PCI Rev Notes -+ * HPT366 4 (HPT366) 0 Other driver -+ * HPT366 4 (HPT366) 1 Other driver -+ * HPT368 4 (HPT366) 2 Other driver -+ * HPT370 4 (HPT366) 3 UDMA100 -+ * HPT370A 4 (HPT366) 4 UDMA100 -+ * HPT372 4 (HPT366) 5 UDMA133 (1) -+ * HPT372N 4 (HPT366) 6 Other driver -+ * HPT372A 5 (HPT372) 1 UDMA133 (1) -+ * HPT372N 5 (HPT372) 2 Other driver -+ * HPT302 6 (HPT302) 1 UDMA133 -+ * HPT302N 6 (HPT302) 2 Other driver -+ * HPT371 7 (HPT371) * UDMA133 -+ * HPT374 8 (HPT374) * UDMA133 4 channel -+ * HPT372N 9 (HPT372N) * Other driver -+ * -+ * (1) UDMA133 support depends on the bus clock -+ */ -+ -+static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ /* HPT370 - UDMA100 */ -+ static struct ata_port_info info_hpt370 = { -+ .sht = &hpt37x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &hpt370_port_ops -+ }; -+ /* HPT370A - UDMA100 */ -+ static struct ata_port_info info_hpt370a = { -+ .sht = &hpt37x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &hpt370a_port_ops -+ }; -+ /* HPT371, 372 and friends - UDMA133 */ -+ static struct ata_port_info info_hpt372 = { -+ .sht = &hpt37x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, -+ .port_ops = &hpt372_port_ops -+ }; -+ /* HPT371, 372 and friends - UDMA100 at 50MHz clock */ -+ static struct ata_port_info info_hpt372_50 = { -+ .sht = &hpt37x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &hpt372_port_ops -+ }; -+ /* HPT374 - UDMA133 */ -+ static struct ata_port_info info_hpt374 = { -+ .sht = &hpt37x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, -+ .port_ops = &hpt374_port_ops -+ }; -+ -+ struct ata_port_info *port_info[2]; -+ struct ata_port_info *port; -+ -+ u8 irqmask; -+ u32 class_rev; -+ u32 freq; -+ -+ int MHz[4] = { 33, 40, 50, 66 }; -+ struct hpt_chip *chip_table; -+ int clock_slot; -+ -+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); -+ class_rev &= 0xFF; -+ -+ if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { -+ /* May be a later chip in disguise. Check */ -+ /* Older chips are in the HPT366 driver. Ignore them */ -+ if (class_rev < 3) -+ return -ENODEV; -+ /* N series chips have their own driver. Ignore */ -+ if (class_rev == 6) -+ return -ENODEV; -+ -+ switch(class_rev) { -+ case 3: -+ port = &info_hpt370; -+ chip_table = &hpt370; -+ break; -+ case 4: -+ port = &info_hpt370a; -+ chip_table = &hpt370a; -+ break; -+ case 5: -+ port = &info_hpt372; -+ chip_table = &hpt372; -+ break; -+ default: -+ printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev); -+ return -ENODEV; -+ } -+ } else { -+ switch(dev->device) { -+ case PCI_DEVICE_ID_TTI_HPT372: -+ /* 372N if rev >= 2*/ -+ if (class_rev >= 2) -+ return -ENODEV; -+ port = &info_hpt372; -+ chip_table = &hpt372a; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT302: -+ /* 302N if rev > 1 */ -+ if (class_rev > 1) -+ return -ENODEV; -+ port = &info_hpt372; -+ /* Check this */ -+ chip_table = &hpt302; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT371: -+ port = &info_hpt372; -+ chip_table = &hpt371; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT374: -+ chip_table = &hpt374; -+ port = &info_hpt374; -+ break; -+ default: -+ printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); -+ return -ENODEV; -+ } -+ } -+ /* Ok so this is a chip we support */ -+ -+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); -+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); -+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); -+ -+ pci_read_config_byte(dev, 0x5A, &irqmask); -+ irqmask &= ~0x10; -+ pci_write_config_byte(dev, 0x5a, irqmask); -+ -+ /* -+ * default to pci clock. make sure MA15/16 are set to output -+ * to prevent drives having problems with 40-pin cables. Needed -+ * for some drives such as IBM-DTLA which will not enter ready -+ * state on reset when PDIAG is a input. -+ */ -+ -+ pci_write_config_byte(dev, 0x5b, 0x23); -+ -+ pci_read_config_dword(dev, 0x70, &freq); -+ if ((freq >> 12) != 0xABCDE) { -+ int i; -+ u8 sr; -+ u32 total = 0; -+ -+ printk(KERN_WARNING "pata_hpt37x: BIOS has not set timing clocks.\n"); -+ -+ /* This is the process the HPT371 BIOS is reported to use */ -+ for(i = 0; i < 128; i++) { -+ pci_read_config_byte(dev, 0x78, &sr); -+ total += sr; -+ udelay(15); -+ } -+ freq = total / 128; -+ } -+ freq &= 0x1FF; -+ -+ /* -+ * Turn the frequency check into a band and then find a timing -+ * table to match it. -+ */ -+ -+ clock_slot = hpt37x_clock_slot(freq, chip_table->base); -+ if (chip_table->clocks[clock_slot] == NULL) { -+ /* -+ * We need to try PLL mode instead -+ */ -+ unsigned int f_low = (MHz[clock_slot] * chip_table->base) / 192; -+ unsigned int f_high = f_low + 2; -+ int adjust; -+ -+ for(adjust = 0; adjust < 8; adjust++) { -+ if (hpt37x_calibrate_dpll(dev)) -+ break; -+ /* See if it'll settle at a fractionally different clock */ -+ if ((adjust & 3) == 3) { -+ f_low --; -+ f_high ++; -+ } -+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); -+ } -+ if (adjust == 8) { -+ printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n"); -+ return -ENODEV; -+ } -+ /* Check if this works for all cases */ -+ port->private_data = hpt370_timings_66; -+ -+ printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]); -+ } else { -+ port->private_data = chip_table->clocks[clock_slot]; -+ /* -+ * Perform a final fixup. The 371 and 372 clock determines -+ * if UDMA133 is available. -+ */ -+ -+ if (clock_slot == 2 && chip_table == &hpt372) { /* 50Mhz */ -+ printk(KERN_WARNING "pata_hpt37x: No UDMA133 support available with 50MHz bus clock.\n"); -+ if (port == &info_hpt372) -+ port = &info_hpt372_50; -+ else BUG(); -+ } -+ printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]); -+ } -+ port_info[0] = port_info[1] = port; -+ /* Now kick off ATA set up */ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id hpt37x[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), }, -+ { 0, }, -+}; -+ -+static struct pci_driver hpt37x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = hpt37x, -+ .probe = hpt37x_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init hpt37x_init(void) -+{ -+ return pci_register_driver(&hpt37x_pci_driver); -+} -+ -+ -+static void __exit hpt37x_exit(void) -+{ -+ pci_unregister_driver(&hpt37x_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT37x/30x"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, hpt37x); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(hpt37x_init); -+module_exit(hpt37x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt3x2n.c linux-2.6.16-rc6/drivers/scsi/pata_hpt3x2n.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_hpt3x2n.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_hpt3x2n.c 2006-03-10 17:06:19.000000000 +0000 -@@ -0,0 +1,580 @@ -+/* -+ * Libata driver for the highpoint 372N and 302N UDMA66 ATA controllers. -+ * -+ * This driver is heavily based upon: -+ * -+ * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 -+ * -+ * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> -+ * Portions Copyright (C) 2001 Sun Microsystems, Inc. -+ * Portions Copyright (C) 2003 Red Hat Inc -+ * -+ * -+ * TODO -+ * 371N -+ * Work out best PLL policy -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "hpt3x2n" -+#define DRV_VERSION "0.1" -+ -+enum { -+ HPT_PCI_FAST = (1 << 31), -+ PCI66 = (1 << 1), -+ USE_DPLL = (1 << 0) -+}; -+ -+struct hpt_clock { -+ u8 xfer_speed; -+ u32 timing; -+}; -+ -+struct hpt_chip { -+ const char *name; -+ struct hpt_clock *clocks[3]; -+}; -+ -+/* key for bus clock timings -+ * bit -+ * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW -+ * DMA. cycles = value + 1 -+ * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file -+ * register access. -+ * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file -+ * register access. -+ * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. -+ * during task file register access. -+ * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA -+ * xfer. -+ * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task -+ * register access. -+ * 28 UDMA enable -+ * 29 DMA enable -+ * 30 PIO_MST enable. if set, the chip is in bus master mode during -+ * PIO. -+ * 31 FIFO enable. -+ */ -+ -+/* 66MHz DPLL clocks */ -+ -+static struct hpt_clock hpt3x2n_clocks[] = { -+ { XFER_UDMA_7, 0x1c869c62 }, -+ { XFER_UDMA_6, 0x1c869c62 }, -+ { XFER_UDMA_5, 0x1c8a9c62 }, -+ { XFER_UDMA_4, 0x1c8a9c62 }, -+ { XFER_UDMA_3, 0x1c8e9c62 }, -+ { XFER_UDMA_2, 0x1c929c62 }, -+ { XFER_UDMA_1, 0x1c9a9c62 }, -+ { XFER_UDMA_0, 0x1c829c62 }, -+ -+ { XFER_MW_DMA_2, 0x2c829c62 }, -+ { XFER_MW_DMA_1, 0x2c829c66 }, -+ { XFER_MW_DMA_0, 0x2c829d2c }, -+ -+ { XFER_PIO_4, 0x0c829c62 }, -+ { XFER_PIO_3, 0x0c829c84 }, -+ { XFER_PIO_2, 0x0c829ca6 }, -+ { XFER_PIO_1, 0x0d029d26 }, -+ { XFER_PIO_0, 0x0d029d5e }, -+ { 0, 0x0d029d5e } -+}; -+ -+/** -+ * hpt3x2n_find_mode - reset the hpt3x2n bus -+ * @ap: ATA port -+ * @speed: transfer mode -+ * -+ * Return the 32bit register programming information for this channel -+ * that matches the speed provided. For the moment the clocks table -+ * is hard coded but easy to change. This will be needed if we use -+ * different DPLLs -+ */ -+ -+static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed) -+{ -+ struct hpt_clock *clocks = hpt3x2n_clocks; -+ -+ while(clocks->xfer_speed) { -+ if (clocks->xfer_speed == speed) -+ return clocks->timing; -+ clocks++; -+ } -+ BUG(); -+} -+ -+/** -+ * hpt3x2n_phy_reset - reset the hpt3x2n bus -+ * @ap: ATA port to reset -+ * -+ * Perform the PHY reset handling for the 3x2N -+ */ -+ -+static void hpt3x2n_phy_reset(struct ata_port *ap) -+{ -+ u8 scr2, ata66; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_byte(pdev, 0x5B, &scr2); -+ pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); -+ /* Cable register now active */ -+ pci_read_config_byte(pdev, 0x5A, &ata66); -+ /* Restore state */ -+ pci_write_config_byte(pdev, 0x5B, scr2); -+ -+ if (ata66 & (1 << ap->hard_port_no)) -+ ap->cbl = ATA_CBL_PATA40; -+ else -+ ap->cbl = ATA_CBL_PATA80; -+ -+ /* Reset the state machine */ -+ pci_write_config_byte(pdev, 0x50, 0x37); -+ pci_write_config_byte(pdev, 0x54, 0x37); -+ udelay(100); -+ -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+/** -+ * hpt3x2n_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Perform PIO mode setup. -+ */ -+ -+static void hpt3x2n_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x07; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt3x2n_find_mode(ap, adev->pio_mode); -+ mode &= ~0x8000000; /* No FIFO in PIO */ -+ mode &= ~0x30070000; /* Leave config bits alone */ -+ reg &= 0x30070000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt3x2n_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * Set up the channel for MWDMA or UDMA modes. Much the same as with -+ * PIO, load the mode number and then set MWDMA or UDMA flag. -+ */ -+ -+static void hpt3x2n_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 addr1, addr2; -+ u32 reg; -+ u32 mode; -+ u8 fast; -+ -+ addr1 = 0x40 + 4 * (adev->devno + 2 * ap->hard_port_no); -+ addr2 = 0x51 + 4 * ap->hard_port_no; -+ -+ /* Fast interrupt prediction disable, hold off interrupt disable */ -+ pci_read_config_byte(pdev, addr2, &fast); -+ fast &= ~0x07; -+ pci_write_config_byte(pdev, addr2, fast); -+ -+ pci_read_config_dword(pdev, addr1, ®); -+ mode = hpt3x2n_find_mode(ap, adev->dma_mode); -+ mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ -+ mode &= ~0xC0000000; /* Leave config bits alone */ -+ reg &= 0xC0000000; /* Strip timing bits */ -+ pci_write_config_dword(pdev, addr1, reg | mode); -+} -+ -+/** -+ * hpt3x2n_bmdma_end - DMA engine stop -+ * @qc: ATA command -+ * -+ * Clean up after the HPT3x2n and later DMA engine -+ */ -+ -+static void hpt3x2n_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int mscreg = 0x50 + 2 * ap->hard_port_no; -+ u8 bwsr_stat, msc_stat; -+ -+ pci_read_config_byte(pdev, 0x6A, &bwsr_stat); -+ pci_read_config_byte(pdev, mscreg, &msc_stat); -+ if (bwsr_stat & (1 << ap->hard_port_no)) -+ pci_write_config_byte(pdev, mscreg, msc_stat | 0x30); -+ ata_bmdma_stop(qc); -+} -+ -+/** -+ * hpt3x2n_set_clock - clock control -+ * @ap: ATA port -+ * @source: 0x21 or 0x23 for PLL or PCI sourced clock -+ * -+ * Switch the ATA bus clock between the PLL and PCI clock sources -+ * while correctly isolating the bus and resetting internal logic -+ * -+ * We must use the DPLL for -+ * - writing -+ * - second channel UDMA7 (SATA ports) or higher -+ * - 66MHz PCI -+ * -+ * or we will underclock the device and get reduced performance. -+ */ -+ -+static void hpt3x2n_set_clock(struct ata_port *ap, int source) -+{ -+ unsigned long bmdma = ap->ioaddr.bmdma_addr; -+ -+ /* Tristate the bus */ -+ outb(0x80, bmdma+0x73); -+ outb(0x80, bmdma+0x77); -+ -+ /* Switch clock and reset channels */ -+ outb(source, bmdma+0x7B); -+ outb(0xC0, bmdma+0x79); -+ -+ /* Reset state machines */ -+ outb(0x37, bmdma+0x70); -+ outb(0x37, bmdma+0x74); -+ -+ /* Complete reset */ -+ outb(0x00, bmdma+0x79); -+ -+ /* Reconnect channels to bus */ -+ outb(0x00, bmdma+0x73); -+ outb(0x00, bmdma+0x77); -+} -+ -+/* Check if our partner interface is busy */ -+ -+static int hpt3x2n_pair_idle(struct ata_port *ap) -+{ -+ struct ata_host_set *host = ap->host_set; -+ struct ata_port *pair = host->ports[ap->hard_port_no ^ 1]; -+ -+ if (pair->hsm_task_state == HSM_ST_IDLE) -+ return 1; -+ return 0; -+} -+ -+static int hpt3x2n_use_dpll(struct ata_port *ap, int reading) -+{ -+ long flags = (long)ap->host_set->private_data; -+ /* See if we should use the DPLL */ -+ if (reading == 0) -+ return USE_DPLL; /* Needed for write */ -+ if (flags & PCI66) -+ return USE_DPLL; /* Needed at 66Mhz */ -+ return 0; -+} -+ -+static int hpt3x2n_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_taskfile *tf = &qc->tf; -+ struct ata_port *ap = qc->ap; -+ int flags = (long)ap->host_set->private_data; -+ -+ if (hpt3x2n_pair_idle(ap)) { -+ int dpll = hpt3x2n_use_dpll(ap, (tf->flags & ATA_TFLAG_WRITE)); -+ if ((flags & USE_DPLL) != dpll) { -+ if (dpll == 1) -+ hpt3x2n_set_clock(ap, 0x21); -+ else -+ hpt3x2n_set_clock(ap, 0x23); -+ } -+ } -+ return ata_qc_issue_prot(qc); -+} -+ -+static struct scsi_host_template hpt3x2n_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+/* -+ * Configuration for HPT3x2n. -+ */ -+ -+static struct ata_port_operations hpt3x2n_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = hpt3x2n_set_piomode, -+ .set_dmamode = hpt3x2n_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = hpt3x2n_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = hpt3x2n_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = hpt3x2n_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * hpt3xn_calibrate_dpll - Calibrate the DPLL loop -+ * @dev: PCI device -+ * -+ * Perform a calibration cycle on the HPT3xN DPLL. Returns 1 if this -+ * succeeds -+ */ -+ -+static int hpt3xn_calibrate_dpll(struct pci_dev *dev) -+{ -+ u8 reg5b; -+ u32 reg5c; -+ int tries; -+ -+ for(tries = 0; tries < 0x5000; tries++) { -+ udelay(50); -+ pci_read_config_byte(dev, 0x5b, ®5b); -+ if (reg5b & 0x80) { -+ /* See if it stays set */ -+ for(tries = 0; tries < 0x1000; tries ++) { -+ pci_read_config_byte(dev, 0x5b, ®5b); -+ /* Failed ? */ -+ if ((reg5b & 0x80) == 0) -+ return 0; -+ } -+ /* Turn off tuning, we have the DPLL set */ -+ pci_read_config_dword(dev, 0x5c, ®5c); -+ pci_write_config_dword(dev, 0x5c, reg5c & ~ 0x100); -+ return 1; -+ } -+ } -+ /* Never went stable */ -+ return 0; -+} -+ -+static int hpt3x2n_pci_clock(struct pci_dev *pdev) -+{ -+ unsigned long freq; -+ u32 fcnt; -+ -+ pci_read_config_dword(pdev, 0x70/*CHECKME*/, &fcnt); -+ if ((fcnt >> 12) != 0xABCDE) { -+ printk(KERN_WARNING "hpt3xn: BIOS clock data not set.\n"); -+ return 33; /* Not BIOS set */ -+ } -+ fcnt &= 0x1FF; -+ -+ freq = (fcnt * 77) / 192; -+ -+ /* Clamp to bands */ -+ if (freq < 40) -+ return 33; -+ if (freq < 45) -+ return 40; -+ if (freq < 55) -+ return 50; -+ return 66; -+} -+ -+/** -+ * hpt3x2n_init_one - Initialise an HPT37X/302 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Initialise an HPT3x2n device. There are some interesting complications -+ * here. Firstly the chip may report 366 and be one of several variants. -+ * Secondly all the timings depend on the clock for the chip which we must -+ * detect and look up -+ * -+ * This is the known chip mappings. It may be missing a couple of later -+ * releases. -+ * -+ * Chip version PCI Rev Notes -+ * HPT372 4 (HPT366) 5 Other driver -+ * HPT372N 4 (HPT366) 6 UDMA133 -+ * HPT372 5 (HPT372) 1 Other driver -+ * HPT372N 5 (HPT372) 2 UDMA133 -+ * HPT302 6 (HPT302) * Other driver -+ * HPT302N 6 (HPT302) > 1 UDMA133 -+ * HPT371 7 (HPT371) * Other driver -+ * HPT371N 7 (HPT371) > 1 UDMA133 -+ * HPT374 8 (HPT374) * Other driver -+ * HPT372N 9 (HPT372N) * UDMA133 -+ * -+ * (1) UDMA133 support depends on the bus clock -+ * -+ * To pin down HPT371N -+ */ -+ -+static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ /* HPT372N and friends - UDMA133 */ -+ static struct ata_port_info info = { -+ .sht = &hpt3x2n_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, -+ .port_ops = &hpt3x2n_port_ops -+ }; -+ struct ata_port_info *port_info[2]; -+ struct ata_port_info *port = &info; -+ -+ u8 irqmask; -+ u32 class_rev; -+ -+ unsigned int pci_mhz; -+ unsigned int f_low, f_high; -+ int adjust; -+ -+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); -+ class_rev &= 0xFF; -+ -+ switch(dev->device) { -+ case PCI_DEVICE_ID_TTI_HPT366: -+ if (class_rev < 6) -+ return -ENODEV; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT372: -+ /* 372N if rev >= 1*/ -+ if (class_rev == 0) -+ return -ENODEV; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT302: -+ if (class_rev < 2) -+ return -ENODEV; -+ break; -+ case PCI_DEVICE_ID_TTI_HPT372N: -+ break; -+ default: -+ printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device); -+ return -ENODEV; -+ } -+ -+ /* Ok so this is a chip we support */ -+ -+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); -+ pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); -+ pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); -+ -+ pci_read_config_byte(dev, 0x5A, &irqmask); -+ irqmask &= ~0x10; -+ pci_write_config_byte(dev, 0x5a, irqmask); -+ -+ /* Tune the PLL. HPT recommend using 75 for SATA, 66 for UDMA133 or -+ 50 for UDMA100. Right now we always use 66 */ -+ -+ pci_mhz = hpt3x2n_pci_clock(dev); -+ -+ f_low = (pci_mhz * 48) / 66; /* PCI Mhz for 66Mhz DPLL */ -+ f_high = f_low + 2; /* Tolerance */ -+ -+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); -+ /* PLL clock */ -+ pci_write_config_byte(dev, 0x5B, 0x21); -+ -+ /* Unlike the 37x we don't try jiggling the frequency */ -+ for(adjust = 0; adjust < 8; adjust++) { -+ if (hpt3xn_calibrate_dpll(dev)) -+ break; -+ pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); -+ } -+ if (adjust == 8) -+ printk(KERN_WARNING "hpt3xn: DPLL did not stabilize.\n"); -+ -+ /* Set our private data up. We only need a few flags so we use -+ it directly */ -+ port->private_data = NULL; -+ if (pci_mhz > 60) -+ port->private_data = (void *)PCI66; -+ -+ /* Now kick off ATA set up */ -+ port_info[0] = port_info[1] = port; -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id hpt3x2n[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N), }, -+ { 0, }, -+}; -+ -+static struct pci_driver hpt3x2n_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = hpt3x2n, -+ .probe = hpt3x2n_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init hpt3x2n_init(void) -+{ -+ return pci_register_driver(&hpt3x2n_pci_driver); -+} -+ -+ -+static void __exit hpt3x2n_exit(void) -+{ -+ pci_unregister_driver(&hpt3x2n_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the Highpoint HPT3x2n/30x"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, hpt3x2n); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(hpt3x2n_init); -+module_exit(hpt3x2n_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_isapnp.c linux-2.6.16-rc6/drivers/scsi/pata_isapnp.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_isapnp.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_isapnp.c 2006-01-21 16:52:31.000000000 +0000 -@@ -0,0 +1,151 @@ -+ -+/* -+ * pata-isapnp.c - ISA PnP PATA controller driver. -+ * Copyright 2005/2006 Red Hat Inc <alan@redhat.com>, all rights reserved. -+ * -+ * Based in part on ide-pnp.c by Andrey Panin <pazke@donpac.ru> -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/isapnp.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/ata.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_isapnp" -+#define DRV_VERSION "0.1" -+ -+static struct scsi_host_template isapnp_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations isapnp_port_ops = { -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * isapnp_init_one - attach an isapnp interface -+ * @idev: PnP device -+ * @dev_id: matching detect line -+ * -+ * Register an ISA bus IDE interface. Such interfaces are PIO 0 and -+ * non shared IRQ. -+ */ -+ -+static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev_id) -+{ -+ struct ata_probe_ent ae; -+ -+ if (pnp_port_valid(idev, 0) == 0) -+ return -ENODEV; -+ if (pnp_port_valid(idev, 1) == 0) -+ return -ENODEV; -+ -+ /* FIXME: Should selected polled PIO here not fail */ -+ if (pnp_irq_valid(idev, 0) == 0) -+ return -ENODEV; -+ -+ memset(&ae, 0, sizeof(struct ata_probe_ent)); -+ INIT_LIST_HEAD(&ae.node); -+ ae.dev = &idev->dev; -+ ae.port_ops = &isapnp_port_ops; -+ ae.sht = &isapnp_sht; -+ ae.n_ports = 1; -+ ae.pio_mask = 1; /* ISA so PIO 0 cycles */ -+ ae.irq = pnp_irq(idev, 0); -+ ae.irq_flags = 0; -+ ae.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IRQ_MASK; -+ ae.port[0].cmd_addr = pnp_port_start(idev, 0); -+ ae.port[0].altstatus_addr = pnp_port_start(idev, 1); -+ ae.port[0].ctl_addr = pnp_port_start(idev, 1); -+ ata_std_ports(&ae.port[0]); -+ -+ if (ata_device_add(&ae) == 0) -+ return -ENODEV; -+ return 0; -+} -+ -+/** -+ * isapnp_remove_one - unplug an isapnp interface -+ * @idev: PnP device -+ * -+ * Remove a previously configured PnP ATA port. Called only on module -+ * unload events as the core does not currently deal with ISAPnP docking. -+ */ -+ -+static void isapnp_remove_one(struct pnp_dev *idev) -+{ -+ struct device *dev = &idev->dev; -+ struct ata_host_set *host_set = dev_get_drvdata(dev); -+ -+ ata_host_set_remove(host_set); -+ dev_set_drvdata(dev, NULL); -+} -+ -+static struct pnp_device_id isapnp_devices[] = { -+ /* Generic ESDI/IDE/ATA compatible hard disk controller */ -+ {.id = "PNP0600", .driver_data = 0}, -+ {.id = ""} -+}; -+ -+static struct pnp_driver isapnp_driver = { -+ .name = DRV_NAME, -+ .id_table = isapnp_devices, -+ .probe = isapnp_init_one, -+ .remove = isapnp_remove_one, -+}; -+ -+static int __init isapnp_init(void) -+{ -+ return pnp_register_driver(&isapnp_driver); -+} -+ -+static void __exit isapnp_exit(void) -+{ -+ pnp_unregister_driver(&isapnp_driver); -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for ISA PnP ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(isapnp_init); -+module_exit(isapnp_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_it8172.c linux-2.6.16-rc6/drivers/scsi/pata_it8172.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_it8172.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_it8172.c 2006-02-16 15:39:11.000000000 +0000 -@@ -0,0 +1,280 @@ -+/* -+ * pata_it8172.c - IT8172 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based heavily on -+ * -+ * BRIEF MODULE DESCRIPTION -+ * IT8172 IDE controller support -+ * -+ * Copyright 2000 MontaVista Software Inc. -+ * Author: MontaVista Software, Inc. -+ * stevel@mvista.com or source@mvista.com -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * TODO -+ * Check for errata -+ * See if we really need to force native mode -+ * PIO timings (also lacking in original) -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "it8172" -+#define DRV_VERSION "0.1.1" -+ -+static void it8172_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits it8172_enable_bits[] = { -+ { 0x00, 0, 0x00, 0x00 }, -+ { 0x40, 1, 0x00, 0x01 } -+ }; -+ -+ if (ap->hard_port_no && !pci_test_config_bits(pdev, &it8172_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * it8172_set_pio_timing - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called by both the pio and dma setup functions to set the controller -+ * timings for PIO transfers. We must load both the mode number and -+ * timing values into the controller. -+ */ -+ -+static void it8172_set_pio_timing(struct ata_port *ap, struct ata_device *adev, int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u16 reg40; -+ -+ pci_read_config_word(pdev, 0x40, ®40); -+ -+ /* -+ * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44 -+ * are being left at the default values of 8 PCI clocks (242 nsec -+ * for a 33 MHz clock). These can be safely shortened at higher -+ * PIO modes. The DIOR/DIOW pulse width and recovery times only -+ * apply to PIO modes, not to the DMA modes. -+ */ -+ -+ /* -+ * Enable port 0x44. The IT8172G spec is confused; it calls -+ * this register the "Slave IDE Timing Register", but in fact, -+ * it controls timing for both master and slave drives. -+ */ -+ -+ reg40 |= 0x4000; -+ if (adev->devno) { -+ reg40 |= 0xC006; -+ if (pio > 1) -+ /* Enable prefetch and IORDY sample-point */ -+ reg40 |= 0x0060; -+ } else { -+ reg40 |= 0xC060; -+ if (pio > 1) -+ /* Enable prefetch and IORDY sample-point */ -+ reg40 |= 0x0006; -+ } -+ /* Write back the enables */ -+ pci_write_config_word(pdev, 0x40, reg40); -+} -+ -+/** -+ * it8172_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. We use a shared helper for this -+ * as the DMA setup must also adjust the PIO timing information. -+ */ -+ -+static void it8172_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ it8172_set_pio_timing(ap, adev, adev->pio_mode - XFER_PIO_0); -+} -+ -+/** -+ * it8172_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the DMA mode setup. We must tune an appropriate PIO -+ * mode to match. -+ */ -+ -+static void it8172_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int dn = (2 * ap->hard_port_no) + adev->devno; -+ u8 reg48, reg4a; -+ int pio; -+ -+ static int pio_map[] = { 1, 3, 4}; -+ /* -+ * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec -+ * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA -+ * transfers on some drives, even though both numbers meet the minimum -+ * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively. -+ * So the faster times are just commented out here. The good news is -+ * that the slower cycle time has very little affect on transfer -+ * performance. -+ */ -+ -+ pci_read_config_byte(pdev, 0x48, ®48); -+ pci_read_config_byte(pdev, 0x4A, ®4a); -+ -+ reg4a &= ~(3 << (4 * dn)); -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ reg48 |= 1 << dn; -+#ifdef UDMA_TIMING_SET -+ reg4a |= ((adev->dma_mode - XFER_UDMA_0) << (4 * dn)); -+#endif -+ pio = 4; -+ } else { -+ pio = pio_map[adev->dma_mode - XFER_MW_DMA_0]; -+ reg48 &= ~ (1 << dn); -+ } -+ pci_write_config_byte(pdev, 0x48, reg48); -+ pci_write_config_byte(pdev, 0x4A, reg4a); -+ it8172_set_pio_timing(ap, adev, pio); -+ -+} -+ -+static struct scsi_host_template it8172_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations it8172_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = it8172_set_piomode, -+ .set_dmamode = it8172_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = it8172_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &it8172_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x06, /* No MWDMA0 support */ -+ .udma_mask = 0x7, -+ .port_ops = &it8172_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ if ((!(PCI_FUNC(dev->devfn) & 1) || -+ (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) -+ return -ENODEV; /* IT8172 is more than an IDE controller */ -+ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id it8172[] = { -+ { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0, }, -+}; -+ -+static struct pci_driver it8172_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = it8172, -+ .probe = it8172_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init it8172_init(void) -+{ -+ return pci_register_driver(&it8172_pci_driver); -+} -+ -+ -+static void __exit it8172_exit(void) -+{ -+ pci_unregister_driver(&it8172_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for ITE IT8172"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, it8172); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(it8172_init); -+module_exit(it8172_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_it821x.c linux-2.6.16-rc6/drivers/scsi/pata_it821x.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_it821x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_it821x.c 2006-03-08 17:14:51.000000000 +0000 -@@ -0,0 +1,790 @@ -+/* -+ * ata-it821x.c - IT821x PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon -+ * -+ * it821x.c -+ * -+ * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 -+ * -+ * Copyright (C) 2004 Red Hat <alan@redhat.com> -+ * -+ * May be copied or modified under the terms of the GNU General Public License -+ * Based in part on the ITE vendor provided SCSI driver. -+ * -+ * Documentation available from -+ * http://www.ite.com.tw/pc/IT8212F_V04.pdf -+ * Some other documents are NDA. -+ * -+ * The ITE8212 isn't exactly a standard IDE controller. It has two -+ * modes. In pass through mode then it is an IDE controller. In its smart -+ * mode its actually quite a capable hardware raid controller disguised -+ * as an IDE controller. Smart mode only understands DMA read/write and -+ * identify, none of the fancier commands apply. The IT8211 is identical -+ * in other respects but lacks the raid mode. -+ * -+ * Errata: -+ * o Rev 0x10 also requires master/slave hold the same DMA timings and -+ * cannot do ATAPI MWDMA. -+ * o The identify data for raid volumes lacks CHS info (technically ok) -+ * but also fails to set the LBA28 and other bits. We fix these in -+ * the IDE probe quirk code. -+ * o If you write LBA48 sized I/O's (ie > 256 sector) in smart mode -+ * raid then the controller firmware dies -+ * o Smart mode without RAID doesn't clear all the necessary identify -+ * bits to reduce the command set to the one used -+ * -+ * This has a few impacts on the driver -+ * - In pass through mode we do all the work you would expect -+ * - In smart mode the clocking set up is done by the controller generally -+ * but we must watch the other limits and filter. -+ * - There are a few extra vendor commands that actually talk to the -+ * controller but only work PIO with no IRQ. -+ * -+ * Vendor areas of the identify block in smart mode are used for the -+ * timing and policy set up. Each HDD in raid mode also has a serial -+ * block on the disk. The hardware extra commands are get/set chip status, -+ * rebuild, get rebuild status. -+ * -+ * In Linux the driver supports pass through mode as if the device was -+ * just another IDE controller. If the smart mode is running then -+ * volumes are managed by the controller firmware and each IDE "disk" -+ * is a raid volume. Even more cute - the controller can do automated -+ * hotplug and rebuild. -+ * -+ * The pass through controller itself is a little demented. It has a -+ * flaw that it has a single set of PIO/MWDMA timings per channel so -+ * non UDMA devices restrict each others performance. It also has a -+ * single clock source per channel so mixed UDMA100/133 performance -+ * isn't perfect and we have to pick a clock. Thankfully none of this -+ * matters in smart mode. ATAPI DMA is not currently supported. -+ * -+ * It seems the smart mode is a win for RAID1/RAID10 but otherwise not. -+ * -+ * TODO -+ * - ATAPI and other speed filtering -+ * - Command filter in smart mode -+ * - RAID configuration ioctls -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+ -+#define DRV_NAME "it821x" -+#define DRV_VERSION "0.2.2" -+ -+struct it821x_dev -+{ -+ unsigned int smart:1, /* Are we in smart raid mode */ -+ timing10:1; /* Rev 0x10 */ -+ u8 clock_mode; /* 0, ATA_50 or ATA_66 */ -+ u8 want[2][2]; /* Mode/Pri log for master slave */ -+ /* We need these for switching the clock when DMA goes on/off -+ The high byte is the 66Mhz timing */ -+ u16 pio[2]; /* Cached PIO values */ -+ u16 mwdma[2]; /* Cached MWDMA values */ -+ u16 udma[2]; /* Cached UDMA values (per drive) */ -+ u16 last_device; /* Master or slave loaded ? */ -+}; -+ -+#define ATA_66 0 -+#define ATA_50 1 -+#define ATA_ANY 2 -+ -+#define UDMA_OFF 0 -+#define MWDMA_OFF 0 -+ -+/* -+ * We allow users to force the card into non raid mode without -+ * flashing the alternative BIOS. This is also neccessary right now -+ * for embedded platforms that cannot run a PC BIOS but are using this -+ * device. -+ */ -+ -+static int it8212_noraid; -+ -+ -+/** -+ * it821x_phy_reset - probe/reset -+ * @ap: ATA port -+ * -+ * Set the cable type and trigger a probe -+ */ -+ -+static void it821x_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA80; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * it821x_program - program the PIO/MWDMA registers -+ * @ap: ATA port -+ * @adev: Device to program -+ * @timing: Timing value (66Mhz in top 8bits, 50 in the low 8) -+ * -+ * Program the PIO/MWDMA timing for this channel according to the -+ * current clock. These share the same register so are managed by -+ * the DMA start/stop sequence as with the old driver. -+ */ -+ -+static void it821x_program(struct ata_port *ap, struct ata_device *adev, u16 timing) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct it821x_dev *itdev = ap->private_data; -+ int channel = ap->hard_port_no; -+ u8 conf; -+ -+ /* Program PIO/MWDMA timing bits */ -+ if (itdev->clock_mode == ATA_66) -+ conf = timing >> 8; -+ else -+ conf = timing & 0xFF; -+ pci_write_config_byte(pdev, 0x54 + 4 * channel, conf); -+} -+ -+ -+/** -+ * it821x_program_udma - program the UDMA registers -+ * @ap: ATA port -+ * @adev: ATA device to update -+ * @timing: Timing bits. Top 8 are for 66Mhz bottom for 50Mhz -+ * -+ * Program the UDMA timing for this drive according to the -+ * current clock. Handles the dual clocks and also knows about -+ * the errata on the 0x10 revision. The UDMA errata is partly handled -+ * here and partly in start_dma. -+ */ -+ -+static void it821x_program_udma(struct ata_port *ap, struct ata_device *adev, u16 timing) -+{ -+ struct it821x_dev *itdev = ap->private_data; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int channel = ap->hard_port_no; -+ int unit = adev->devno; -+ u8 conf; -+ -+ /* Program UDMA timing bits */ -+ if (itdev->clock_mode == ATA_66) -+ conf = timing >> 8; -+ else -+ conf = timing & 0xFF; -+ if (itdev->timing10 == 0) -+ pci_write_config_byte(pdev, 0x56 + 4 * channel + unit, conf); -+ else { -+ /* Early revision must be programmed for both together */ -+ pci_write_config_byte(pdev, 0x56 + 4 * channel, conf); -+ pci_write_config_byte(pdev, 0x56 + 4 * channel + 1, conf); -+ } -+} -+ -+/** -+ * it821x_clock_strategy -+ * @ap: ATA interface -+ * @adev: ATA device being updated -+ * -+ * Select between the 50 and 66Mhz base clocks to get the best -+ * results for this interface. -+ */ -+ -+static void it821x_clock_strategy(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct it821x_dev *itdev = ap->private_data; -+ u8 unit = adev->devno; -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ -+ int clock, altclock; -+ u8 v; -+ int sel = 0; -+ -+ /* Look for the most wanted clocking */ -+ if (itdev->want[0][0] > itdev->want[1][0]) { -+ clock = itdev->want[0][1]; -+ altclock = itdev->want[1][1]; -+ } else { -+ clock = itdev->want[1][1]; -+ altclock = itdev->want[0][1]; -+ } -+ -+ /* Master doesn't care does the slave ? */ -+ if (clock == ATA_ANY) -+ clock = altclock; -+ -+ /* Nobody cares - keep the same clock */ -+ if (clock == ATA_ANY) -+ return; -+ /* No change */ -+ if (clock == itdev->clock_mode) -+ return; -+ -+ /* Load this into the controller ? */ -+ if (clock == ATA_66) -+ itdev->clock_mode = ATA_66; -+ else { -+ itdev->clock_mode = ATA_50; -+ sel = 1; -+ } -+ pci_read_config_byte(pdev, 0x50, &v); -+ v &= ~(1 << (1 + ap->hard_port_no)); -+ v |= sel << (1 + ap->hard_port_no); -+ pci_write_config_byte(pdev, 0x50, v); -+ -+ /* -+ * Reprogram the UDMA/PIO of the pair drive for the switch -+ * MWDMA will be dealt with by the dma switcher -+ */ -+ if (pair && itdev->udma[1-unit] != UDMA_OFF) { -+ it821x_program_udma(ap, pair, itdev->udma[1-unit]); -+ it821x_program(ap, pair, itdev->pio[1-unit]); -+ } -+ /* -+ * Reprogram the UDMA/PIO of our drive for the switch. -+ * MWDMA will be dealt with by the dma switcher -+ */ -+ if (itdev->udma[unit] != UDMA_OFF) { -+ it821x_program_udma(ap, adev, itdev->udma[unit]); -+ it821x_program(ap, adev, itdev->pio[unit]); -+ } -+} -+ -+/** -+ * it821x_passthru_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Configure for PIO mode. This is complicated as the register is -+ * shared by PIO and MWDMA and for both channels. -+ */ -+ -+static void it821x_passthru_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ /* Spec says 89 ref driver uses 88 */ -+ static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; -+ static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; -+ -+ struct it821x_dev *itdev = ap->private_data; -+ int unit = adev->devno; -+ int mode_wanted = adev->pio_mode - XFER_PIO_0; -+ -+ /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ -+ itdev->want[unit][1] = pio_want[mode_wanted]; -+ itdev->want[unit][0] = 1; /* PIO is lowest priority */ -+ itdev->pio[unit] = pio[mode_wanted]; -+ it821x_clock_strategy(ap, adev); -+ it821x_program(ap, adev, itdev->pio[unit]); -+} -+ -+/** -+ * it821x_passthru_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Set up the DMA modes. The actions taken depend heavily on the mode -+ * to use. If UDMA is used as is hopefully the usual case then the -+ * timing register is private and we need only consider the clock. If -+ * we are using MWDMA then we have to manage the setting ourself as -+ * we switch devices and mode. -+ */ -+ -+static void it821x_passthru_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u16 dma[] = { 0x8866, 0x3222, 0x3121 }; -+ static u8 mwdma_want[] = { ATA_ANY, ATA_66, ATA_ANY }; -+ static u16 udma[] = { 0x4433, 0x4231, 0x3121, 0x2121, 0x1111, 0x2211, 0x1111 }; -+ static u8 udma_want[] = { ATA_ANY, ATA_50, ATA_ANY, ATA_66, ATA_66, ATA_50, ATA_66 }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct it821x_dev *itdev = ap->private_data; -+ int channel = ap->hard_port_no; -+ int unit = adev->devno; -+ u8 conf; -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ int mode_wanted = adev->dma_mode - XFER_UDMA_0; -+ -+ itdev->want[unit][1] = udma_want[mode_wanted]; -+ itdev->want[unit][0] = 3; /* UDMA is high priority */ -+ itdev->mwdma[unit] = MWDMA_OFF; -+ itdev->udma[unit] = udma[mode_wanted]; -+ if (mode_wanted >= 5) -+ itdev->udma[unit] |= 0x8080; /* UDMA 5/6 select on */ -+ -+ /* UDMA on. Again revision 0x10 must do the pair */ -+ pci_read_config_byte(pdev, 0x50, &conf); -+ if (itdev->timing10) -+ conf &= channel ? 0x9F: 0xE7; -+ else -+ conf &= ~ (1 << (3 + 2 * channel + unit)); -+ pci_write_config_byte(pdev, 0x50, conf); -+ it821x_clock_strategy(ap, adev); -+ it821x_program_udma(ap, adev, itdev->udma[unit]); -+ } else { -+ int mode_wanted = adev->dma_mode - XFER_UDMA_0; -+ -+ itdev->want[unit][1] = mwdma_want[mode_wanted]; -+ itdev->want[unit][0] = 2; /* MWDMA is low priority */ -+ itdev->mwdma[unit] = dma[mode_wanted]; -+ itdev->udma[unit] = UDMA_OFF; -+ -+ /* UDMA bits off - Revision 0x10 do them in pairs */ -+ pci_read_config_byte(pdev, 0x50, &conf); -+ if (itdev->timing10) -+ conf |= channel ? 0x60: 0x18; -+ else -+ conf |= 1 << (3 + 2 * channel + unit); -+ pci_write_config_byte(pdev, 0x50, conf); -+ it821x_clock_strategy(ap, adev); -+ } -+} -+ -+/** -+ * it821x_passthru_dma_start - DMA start callback -+ * @qc: Command in progress -+ * -+ * Usually drivers set the DMA timing at the point the set_dmamode call -+ * is made. IT821x however requires we load new timings on the -+ * transitions in some cases. -+ */ -+ -+static void it821x_passthru_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ struct it821x_dev *itdev = ap->private_data; -+ int unit = adev->devno; -+ -+ if (itdev->mwdma[unit] != MWDMA_OFF) -+ it821x_program(ap, adev, itdev->mwdma[unit]); -+ else if (itdev->udma[unit] != UDMA_OFF && itdev->timing10) -+ it821x_program_udma(ap, adev, itdev->udma[unit]); -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * it821x_passthru_dma_stop - DMA stop callback -+ * @qc: ATA command -+ * -+ * We loaded new timings in dma_start, as a result we need to restore -+ * the PIO timings in dma_stop so that the next command issue gets the -+ * right clock values. -+ */ -+ -+static void it821x_passthru_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ struct it821x_dev *itdev = ap->private_data; -+ int unit = adev->devno; -+ -+ ata_bmdma_stop(qc); -+ if (itdev->mwdma[unit] != MWDMA_OFF) -+ it821x_program(ap, adev, itdev->pio[unit]); -+} -+ -+ -+/** -+ * it821x_passthru_dev_select - Select master/slave -+ * @ap: ATA port -+ * @device: Device number (not pointer) -+ * -+ * Device selection hook. If neccessary perform clock switching -+ */ -+ -+void it821x_passthru_dev_select(struct ata_port *ap, unsigned int device) -+{ -+ struct it821x_dev *itdev = ap->private_data; -+ if (itdev && device != itdev->last_device) { -+ struct ata_device *adev = &ap->device[device]; -+ it821x_program(ap, adev, itdev->pio[adev->devno]); -+ itdev->last_device = device; -+ } -+} -+ -+/** -+ * it821x_passthru_qc_issue_prot - wrap qc issue prot -+ * @qc: command -+ * -+ * Wrap the command issue sequence for the IT821x. We need to -+ * perform out own device selection timing loads before the -+ * usual happenings kick off -+ */ -+ -+static int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ it821x_passthru_dev_select(qc->ap, qc->dev->devno); -+ return ata_qc_issue_prot(qc); -+} -+ -+/** -+ * it821x_smart_set_mode - mode setting -+ * @ap: interface to set up -+ * -+ * Use a non standard set_mode function. We don't want to be tuned. -+ * The BIOS configured everything. Our job is not to fiddle. We -+ * read the dma enabled bits from the PCI configuration of the device -+ * and respect them. -+ */ -+ -+static void it821x_smart_set_mode(struct ata_port *ap) -+{ -+ int dma_enabled; -+ int i; -+ -+ /* Bits 5 and 6 indicate if DMA is active on master/slave */ -+ dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ /* We don't really care */ -+ dev->pio_mode = XFER_PIO_0; -+ dev->dma_mode = XFER_MW_DMA_0; -+ /* We do need the right mode information for DMA or PIO -+ and this comes from the current configuration flags */ -+ if (dma_enabled & (1 << (5 + i))) { -+ dev->xfer_mode = XFER_MW_DMA_0; -+ dev->xfer_shift = ATA_SHIFT_MWDMA; -+ dev->flags &= ~ATA_DFLAG_PIO; -+ } else { -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+ } -+} -+ -+/** -+ * it821x_dev_config - Called each device identify -+ * @ap: ATA port -+ * @adev: Device that has just been identified -+ * -+ * Perform the initial setup needed for each device that is chip -+ * special. In our case we need to lock the sector count to avoid -+ * blowing the brains out of the firmware with large LBA48 requests -+ * -+ * FIXME: When FUA appears we need to block FUA too. And SMART and -+ * basically we need to filter commands for this chip. -+ */ -+ -+static void it821x_dev_config(struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned char model_num[40]; -+ char *s; -+ unsigned int len; -+ -+ /* This block ought to be a library routine as it is in several -+ drivers now */ -+ -+ ata_dev_id_string(adev->id, model_num, ATA_ID_PROD_OFS, -+ sizeof(model_num)); -+ s = &model_num[0]; -+ len = strnlen(s, sizeof(model_num)); -+ -+ /* ATAPI specifies that empty space is blank-filled; remove blanks */ -+ while ((len > 0) && (s[len - 1] == ' ')) { -+ len--; -+ s[len] = 0; -+ } -+ -+ if(ap->host->max_sectors > 255) { -+ ap->host->max_sectors = 255; -+ ap->host->hostt->max_sectors = 255; -+ } -+ adev->flags |= ATA_DFLAG_LOCK_SECTORS; -+ -+ if (strstr(model_num, "Integrated Technology Express")) { -+ /* RAID mode */ -+ printk(KERN_INFO "IT821x %sRAID%d volume", -+ adev->id[147]?"Bootable ":"", -+ adev->id[129]); -+ if(adev->id[129] != 1) -+ printk("(%dK stripe)", adev->id[146]); -+ printk(".\n"); -+ } -+} -+ -+ -+/** -+ * it821x_check_atapi_dma - ATAPI DMA handler -+ * @qc: Command we are about to issue -+ * -+ * Decide if this ATAPI command can be issued by DMA on this -+ * controller. Return 0 if it can be. -+ */ -+ -+static int it821x_check_atapi_dma(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct it821x_dev *itdev = ap->private_data; -+ -+ /* No ATAPI DMA in smart mode */ -+ if (itdev->smart) -+ return -EOPNOTSUPP; -+ /* No ATAPI DMA on rev 10 */ -+ if (itdev->timing10) -+ return -EOPNOTSUPP; -+ /* Cool */ -+ return 0; -+} -+ -+ -+/** -+ * it821x_port_start - port setup -+ * @ap: ATA port being set up -+ * -+ * The it821x needs to maintain private data structures and also to -+ * use the standard PCI interface which lacks support for this -+ * functionality. We instead set up the private data on the port -+ * start hook, and tear it down on port stop -+ */ -+ -+static int it821x_port_start(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct it821x_dev *itdev; -+ u8 conf; -+ -+ int ret = ata_port_start(ap); -+ if (ret < 0) -+ return ret; -+ -+ ap->private_data = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL); -+ if (ap->private_data == NULL) { -+ ata_port_stop(ap); -+ return -ENOMEM; -+ } -+ -+ itdev = ap->private_data; -+ memset(itdev, 0, sizeof(struct it821x_dev)); -+ -+ pci_read_config_byte(pdev, 0x50, &conf); -+ -+ if (conf & 1) { -+ itdev->smart = 1; -+ /* Long I/O's although allowed in LBA48 space cause the -+ onboard firmware to enter the twighlight zone */ -+ /* No ATAPI DMA in this mode either */ -+ } -+ /* Pull the current clocks from 0x50 */ -+ if (conf & (1 << (1 + ap->hard_port_no))) -+ itdev->clock_mode = ATA_50; -+ else -+ itdev->clock_mode = ATA_66; -+ -+ itdev->want[0][1] = ATA_ANY; -+ itdev->want[1][1] = ATA_ANY; -+ itdev->last_device = -1; -+ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &conf); -+ if (conf == 0x10) { -+ itdev->timing10 = 1; -+ /* Need to disable ATAPI DMA for this case */ -+ if (!itdev->smart) -+ printk(KERN_WARNING DRV_NAME": Revision 0x10, workarounds activated.\n"); -+ } -+ -+ return 0; -+} -+ -+/** -+ * it821x_port_stop - port shutdown -+ * @ap: ATA port being removed -+ * -+ * Release the private objects we added in it821x_port_start -+ */ -+ -+static void it821x_port_stop(struct ata_port *ap) { -+ kfree(ap->private_data); -+ ap->private_data = NULL; /* We want an OOPS if we reuse this -+ too late! */ -+ ata_port_stop(ap); -+} -+ -+static struct scsi_host_template it821x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ /* 255 sectors to begin with. This is locked in smart mode but not -+ in pass through */ -+ .max_sectors = 255, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations it821x_smart_port_ops = { -+ .set_mode = it821x_smart_set_mode, -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .check_atapi_dma= it821x_check_atapi_dma, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ .dev_config = it821x_dev_config, -+ -+ .phy_reset = it821x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = it821x_port_start, -+ .port_stop = it821x_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations it821x_passthru_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = it821x_passthru_set_piomode, -+ .set_dmamode = it821x_passthru_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .check_atapi_dma= it821x_check_atapi_dma, -+ .dev_select = it821x_passthru_dev_select, -+ -+ .phy_reset = it821x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = it821x_passthru_bmdma_start, -+ .bmdma_stop = it821x_passthru_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = it821x_passthru_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ .irq_handler = ata_interrupt, -+ .port_start = it821x_port_start, -+ .port_stop = it821x_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static void __devinit it821x_disable_raid(struct pci_dev *pdev) -+{ -+ /* Reset local CPU, and set BIOS not ready */ -+ pci_write_config_byte(pdev, 0x5E, 0x01); -+ -+ /* Set to bypass mode, and reset PCI bus */ -+ pci_write_config_byte(pdev, 0x50, 0x00); -+ pci_write_config_word(pdev, PCI_COMMAND, -+ PCI_COMMAND_PARITY | PCI_COMMAND_IO | -+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); -+ pci_write_config_word(pdev, 0x40, 0xA0F3); -+ -+ pci_write_config_dword(pdev,0x4C, 0x02040204); -+ pci_write_config_byte(pdev, 0x42, 0x36); -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20); -+} -+ -+ -+static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ u8 conf; -+ -+ static struct ata_port_info info_smart = { -+ .sht = &it821x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &it821x_smart_port_ops -+ }; -+ static struct ata_port_info info_passthru = { -+ .sht = &it821x_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, -+ .port_ops = &it821x_passthru_port_ops -+ }; -+ static struct ata_port_info *port_info[2]; -+ -+ static char *mode[2] = { "pass through", "smart" }; -+ -+ /* Force the card into bypass mode if so requested */ -+ if (it8212_noraid) { -+ printk(KERN_INFO DRV_NAME ": forcing bypass mode.\n"); -+ it821x_disable_raid(pdev); -+ } -+ pci_read_config_byte(pdev, 0x50, &conf); -+ conf &= 1; -+ -+ printk(KERN_INFO DRV_NAME ": controller in %s mode.\n", mode[conf]); -+ if (conf == 0) -+ port_info[0] = port_info[1] = &info_passthru; -+ else -+ port_info[0] = port_info[1] = &info_smart; -+ -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static struct pci_device_id it821x[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8211), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212), }, -+ { 0, }, -+}; -+ -+static struct pci_driver it821x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = it821x, -+ .probe = it821x_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init it821x_init(void) -+{ -+ return pci_register_driver(&it821x_pci_driver); -+} -+ -+ -+static void __exit it821x_exit(void) -+{ -+ pci_unregister_driver(&it821x_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for the IT8211/IT8212 IDE RAID controller"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, it821x); -+MODULE_VERSION(DRV_VERSION); -+ -+ -+module_param_named(noraid, it8212_noraid, int, S_IRUGO); -+MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode"); -+ -+module_init(it821x_init); -+module_exit(it821x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_legacy.c linux-2.6.16-rc6/drivers/scsi/pata_legacy.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_legacy.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_legacy.c 2006-02-16 15:33:52.000000000 +0000 -@@ -0,0 +1,672 @@ -+ -+/* -+ * pata-legacy.c - Legacy port PATA/SATA controller driver. -+ * Copyright 2005/2006 Red Hat Inc <alan@redhat.com>, all rights reserved. -+ * -+ * An ATA driver for the legacy ATA ports. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/ata.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "legacy" -+#define DRV_VERSION "0.3.1" -+ -+#define NR_HOST 6 -+ -+static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; -+static int legacy_irq[NR_HOST] = { 15, 14, 11, 10, 8, 12 }; -+ -+static struct ata_host_set *legacy_host[NR_HOST]; -+static int nr_legacy_host; -+static int legacy_all; -+static int ht6560a; -+static int ht6560b; -+static int opti82c611a; -+ -+/** -+ * legacy_set_mode - mode setting -+ * @ap: IDE interface -+ * -+ * Use a non standard set_mode function. We don't want to be tuned. -+ * -+ * The BIOS configured everything. Our job is not to fiddle. Just use -+ * whatever PIO the hardware is using and leave it at that. When we -+ * get some kind of nice user driven API for control then we can -+ * expand on this as per hdparm in the base kernel. -+ */ -+ -+static void legacy_set_mode(struct ata_port *ap) -+{ -+ int i; -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ dev->pio_mode = XFER_PIO_0; -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+} -+ -+static struct scsi_host_template legacy_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations legacy_port_ops = { -+ .set_mode = legacy_set_mode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer_noirq, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Promise 20230C and 20620 support -+ * -+ * This controller supports PIO0 to PIO2. We set PIO timings conservatively to -+ * allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to -+ * controller and PIO'd to the host and not supported. -+ */ -+ -+static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ int tries = 5; -+ int pio = adev->pio_mode - XFER_PIO_0; -+ u8 rt; -+ -+ do -+ { -+ inb(0x1F5); -+ outb(inb(0x1F2) | 0x80, 0x1F2); -+ inb(0x1F2); -+ inb(0x3F6); -+ inb(0x3F6); -+ inb(0x1F2); -+ inb(0x1F2); -+ } -+ while((inb(0x1F2) & 0x80) && --tries); -+ -+ outb(inb(0x1F4) & 0x07, 0x1F4); -+ -+ rt = inb(0x1F3); -+ rt &= 0x07 << (3 * adev->devno); -+ rt |= (3 * pio) << (3 * adev->devno); -+ -+ udelay(100); -+ outb(inb(0x1F2) | 0x01, 0x1F2); -+ udelay(100); -+ inb(0x1F5); -+ -+} -+ -+static void pdc_data_xfer_vlb(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) -+{ -+ int slop = buflen & 3; -+ unsigned long flags; -+ -+ if (ata_id_has_dword_io(adev->id)) { -+ local_irq_save(flags); -+ -+ /* Perform the 32bit I/O synchronization sequence */ -+ inb(ap->ioaddr.nsect_addr); -+ inb(ap->ioaddr.nsect_addr); -+ inb(ap->ioaddr.nsect_addr); -+ -+ /* Now the data */ -+ -+ if (write_data) -+ outsl(ap->ioaddr.data_addr, buf, buflen >> 2); -+ else -+ insl(ap->ioaddr.data_addr, buf, buflen >> 2); -+ -+ if (unlikely(slop)) { -+ u32 pad; -+ if (write_data) { -+ memcpy(&pad, buf + buflen - slop, slop); -+ outl(le32_to_cpu(pad), ap->ioaddr.data_addr); -+ } else { -+ pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); -+ memcpy(buf + buflen - slop, &pad, slop); -+ } -+ } -+ local_irq_restore(flags); -+ } -+ else -+ ata_pio_data_xfer_noirq(ap, adev, buf, buflen, write_data); -+} -+ -+static struct ata_port_operations pdc20230_port_ops = { -+ .set_piomode = pdc20230_set_piomode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = pdc_data_xfer_vlb, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Holtek 6560A support -+ * -+ * This controller supports PIO0 to PIO2 (no IORDY even though higher timings -+ * can be loaded). -+ */ -+ -+static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ u8 active, recover; -+ struct ata_timing t; -+ -+ /* Get the timing data in cycles. For now play safe at 50Mhz */ -+ ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); -+ -+ active = FIT(t.active, 2, 15); -+ recover = FIT(t.recover, 4, 15); -+ -+ inb(0x3E6); -+ inb(0x3E6); -+ inb(0x3E6); -+ inb(0x3E6); -+ -+ outb(recover << 4 | active, ap->ioaddr.device_addr); -+ inb(ap->ioaddr.status_addr); -+} -+ -+static struct ata_port_operations ht6560a_port_ops = { -+ .set_piomode = ht6560a_set_piomode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, /* Check vlb/noirq */ -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Holtek 6560B support -+ * -+ * This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting -+ * unless we see an ATAPI device in which case we force it off. -+ * -+ * FIXME: need to implement 2nd channel support. -+ */ -+ -+static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ u8 active, recover; -+ struct ata_timing t; -+ -+ /* Get the timing data in cycles. For now play safe at 50Mhz */ -+ ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); -+ -+ active = FIT(t.active, 2, 15); -+ recover = FIT(t.recover, 2, 16); -+ recover &= 0x15; -+ -+ inb(0x3E6); -+ inb(0x3E6); -+ inb(0x3E6); -+ inb(0x3E6); -+ -+ outb(recover << 4 | active, ap->ioaddr.device_addr); -+ -+ if (adev->class != ATA_DEV_ATA) { -+ u8 rconf = inb(0x3E6); -+ if (rconf & 0x24) { -+ rconf &= ~ 0x24; -+ outb(rconf, 0x3E6); -+ } -+ } -+ inb(ap->ioaddr.status_addr); -+} -+ -+static struct ata_port_operations ht6560b_port_ops = { -+ .set_piomode = ht6560b_set_piomode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, /* FIXME: Check 32bit and noirq */ -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/* -+ * Opti 82C611A -+ * -+ * This controller supports PIO0 to PIO3. -+ */ -+ -+static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ u8 active, recover, setup; -+ struct ata_timing t; -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ int clock; -+ int khz[4] = { 50000, 40000, 33000, 25000 }; -+ u8 rc; -+ -+ /* Enter configuration mode */ -+ inb(ap->ioaddr.error_addr); -+ inb(ap->ioaddr.error_addr); -+ -+ /* Read VLB clock strapping */ -+ clock = 1000000000 / khz[inb(ap->ioaddr.lbah_addr) & 0x03]; -+ -+ /* Get the timing data in cycles */ -+ ata_timing_compute(adev, adev->pio_mode, &t, clock, 1000); -+ -+ /* Setup timing is shared */ -+ if (pair) { -+ struct ata_timing tp; -+ ata_timing_compute(pair, pair->pio_mode, &tp, clock, 1000); -+ -+ ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); -+ } -+ -+ active = FIT(t.active, 2, 17) - 2; -+ recover = FIT(t.recover, 1, 16) - 1; -+ setup = FIT(t.setup, 1, 4) - 1; -+ -+ /* Select the right timing bank for write timing */ -+ rc = inb(ap->ioaddr.lbal_addr); -+ rc &= 0x7F; -+ rc |= (adev->devno << 7); -+ outb(rc, ap->ioaddr.lbal_addr); -+ -+ /* Write the timings */ -+ outb(active << 4 | recover, ap->ioaddr.error_addr); -+ -+ /* Select the right bank for read timings, also -+ load the shared timings for address */ -+ rc = inb(ap->ioaddr.device_addr); -+ rc &= 0xC0; -+ rc |= adev->devno; /* Index select */ -+ rc |= (setup << 4) | 0x04; -+ outb(rc, ap->ioaddr.device_addr); -+ -+ /* Load the read timings */ -+ outb(active << 4 | recover, ap->ioaddr.data_addr); -+ -+ /* Ensure the timing register mode is right */ -+ rc = inb (ap->ioaddr.lbal_addr); -+ rc &= 0x73; -+ rc |= 0x84; -+ outb(rc, ap->ioaddr.lbal_addr); -+ -+ /* Exit command mode */ -+ outb(0x82, ap->ioaddr.nsect_addr); -+} -+ -+static struct ata_port_operations opti82c611a_port_ops = { -+ .set_piomode = opti82c611a_set_piomode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * legacy_init_one - attach a legacy interface -+ * @io: I/O port start -+ * @ctrl: control port -+ * @irq: interrupt line -+ * -+ * Register an ISA bus IDE interface. Such interfaces are PIO and we -+ * assume do not support IRQ sharing. -+ */ -+ -+static __init int legacy_init_one(unsigned long io, unsigned long ctrl, int irq) -+{ -+ struct ata_probe_ent ae; -+ int ret; -+ struct ata_port_operations *ops = &legacy_port_ops; -+ int pio_mask = 0x1F; -+ -+ if (request_region(io, 8, "pata_legacy") == NULL) -+ return -EBUSY; -+ if (request_region(ctrl, 1, "pata_legacy") == NULL) { -+ release_region(io, 8); -+ return -EBUSY; -+ } -+ -+ if (ht6560a == 1 && (io == 0x1F0 || io == 0x170)) { -+ ops = &ht6560a_port_ops; -+ pio_mask = 0x07; -+ } -+ if (ht6560b == 1 && (io == 0x1F0 || io == 0x170)) { -+ ops = &ht6560b_port_ops; -+ pio_mask = 0x1F; -+ } -+ if (opti82c611a == 1 && (io == 0x1F0 || io == 0x170)) { -+ ops = &opti82c611a_port_ops; -+ pio_mask = 0x0F; -+ } -+ else if (io == 0x1F0) { -+ /* Probes */ -+ inb(0x1F5); -+ outb(inb(0x1F2) | 0x80, 0x1F2); -+ inb(0x1F2); -+ inb(0x3F6); -+ inb(0x3F6); -+ inb(0x1F2); -+ inb(0x1F2); -+ -+ if ((inb(0x1F2) & 0x80) == 0) { -+ /* PDC20230 or 20630 ? */ -+ printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n"); -+ pio_mask = 0x07; -+ ops = &pdc20230_port_ops; -+ udelay(100); -+ inb(0x1F5); -+ } else { -+ outb(0x55, 0x1F2); -+ inb(0x1F2); -+ inb(0x1F2); -+ if (inb(0x1F2) == 0x00) { -+ printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n"); -+ } -+ } -+ } -+ memset(&ae, 0, sizeof(struct ata_probe_ent)); -+ INIT_LIST_HEAD(&ae.node); -+ ae.dev = NULL; -+ ae.port_ops = ops; -+ ae.sht = &legacy_sht; -+ ae.n_ports = 1; -+ ae.pio_mask = pio_mask; -+ ae.irq = irq; -+ ae.irq_flags = 0; -+ ae.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IRQ_MASK; -+ ae.port[0].cmd_addr = io; -+ ae.port[0].altstatus_addr = ctrl; -+ ae.port[0].ctl_addr = ctrl; -+ ata_std_ports(&ae.port[0]); -+ -+ ret = ata_device_add(&ae); -+ if (ret == 0) -+ return -ENODEV; -+ -+ legacy_host[nr_legacy_host++] = ae.host_set; -+ return 0; -+} -+ -+/** -+ * legacy_check_special_cases - ATA special cases -+ * @p: PCI device to check -+ * @master: set this if we find an ATA master -+ * @master: set this if we find an ATA secondary -+ * -+ * A small number of vendors implemented early PCI ATA interfaces on bridge logic -+ * without the ATA interface being PCI visible. Where we have a matching PCI driver -+ * we must skip the relevant device here. If we don't know about it then the legacy -+ * driver is the right driver anyway. -+ */ -+ -+static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary) -+{ -+ /* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */ -+ if (p->vendor == 0x1078 && p->device == 0x0000) { -+ *primary = *secondary = 1; -+ return; -+ } -+ /* Cyrix CS5520 pre SFF MWDMA ATA on the bridge */ -+ if (p->vendor == 0x1078 && p->device == 0x0002) { -+ *primary = *secondary = 1; -+ return; -+ } -+ /* Intel MPIIX - PIO ATA on non PCI side of bridge */ -+ if (p->vendor == 0x8086 && p->device == 0x1234) { -+ u16 r; -+ pci_read_config_word(p, 0x6C, &r); -+ if (r & 0x8000) { /* ATA port enabled */ -+ if (r & 0x4000) -+ *secondary = 1; -+ else -+ *primary = 1; -+ } -+ return; -+ } -+} -+ -+/** -+ * legacy_init - attach legacy interfaces -+ * -+ * Attach legacy IDE interfaces by scanning the usual IRQ/port suspects. -+ * Right now we do not scan the ide0 and ide1 address but should do so -+ * for non PCI systems or systems with no PCI IDE legacy mode devices. -+ * If you fix that note there are special cases to consider like VLB -+ * drivers and CS5510/20. -+ */ -+ -+static __init int legacy_init(void) -+{ -+ int i; -+ int ct = 0; -+ int primary = 0; -+ int secondary = 0; -+ int last_port = NR_HOST; -+ -+ struct pci_dev *p = NULL; -+ -+ for_each_pci_dev(p) { -+ int r; -+ /* Check for any overlap of the system ATA mappings. Native mode controllers -+ stuck on these addresses or some devices in 'raid' mode won't be found by -+ the storage class test */ -+ for (r = 0; r < 6; r++) { -+ if (pci_resource_start(p, r) == 0x1f0) -+ primary = 1; -+ if (pci_resource_start(p, r) == 0x170) -+ secondary = 1; -+ } -+ /* Check for special cases */ -+ legacy_check_special_cases(p, &primary, &secondary); -+ -+ /* If PCI bus is present then don't probe for tertiary legacy ports */ -+ if (legacy_all == 0) -+ last_port = 2; -+ } -+ -+ -+ for (i = 0; i < last_port; i++) { -+ /* Skip primary if we have seen a PCI one */ -+ if (i == 0 && primary == 1) -+ continue; -+ /* Skip secondary if we have seen a PCI one */ -+ if (i == 1 && secondary == 1) -+ continue; -+ if (legacy_init_one(legacy_port[i], -+ legacy_port[i] + 0x0206, -+ legacy_irq[i]) == 0) -+ ct++; -+ } -+ if (ct != 0) -+ return 0; -+ return -ENODEV; -+} -+ -+static __exit void legacy_exit(void) -+{ -+ int i; -+ -+ for (i = 0; i < nr_legacy_host; i++) { -+ struct ata_port *ap =legacy_host[i]->ports[0]; -+ unsigned long io = ap->ioaddr.cmd_addr; -+ unsigned long ctrl = ap->ioaddr.ctl_addr; -+ ata_host_set_remove(legacy_host[i]); -+ release_region(io, 8); -+ release_region(ctrl, 1); -+ } -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for legacy ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+/** -+ * legacy_probe_all - setup argument handler -+ * @unused: unused -+ * -+ * Called when the probe_all argument is passed to this driver. This indicates -+ * that we should check all the legacy ATA addresses even if PCI is present. Should -+ * only ever be needed on very strange PCI/legacy combinations -+ */ -+ -+static int __init legacy_probe_all(char *unused) -+{ -+ legacy_all = 1; -+ return 1; -+} -+ -+__setup("probe-all", legacy_probe_all); -+ -+/** -+ * legacy_ht6560a - setup argument handler -+ * @unused: unused -+ * -+ * Called when the ht6560a argument is passed to this driver. This indicates -+ * that we should check all the legacy ATA addresses even if PCI is present. Should -+ * only ever be needed on very strange PCI/legacy combinations -+ */ -+ -+static int __init legacy_ht6560a(char *unused) -+{ -+ ht6560a = 1; -+ return 1; -+} -+ -+__setup("ht6560a", legacy_ht6560a); -+ -+/** -+ * legacy_ht6560b - setup argument handler -+ * @unused: unused -+ * -+ * Called when the ht6560b argument is passed to this driver. This indicates -+ * that we should check all the legacy ATA addresses even if PCI is present. Should -+ * only ever be needed on very strange PCI/legacy combinations -+ */ -+ -+static int __init legacy_ht6560b(char *unused) -+{ -+ ht6560b = 1; -+ return 1; -+} -+ -+__setup("ht6560b", legacy_ht6560b); -+ -+/** -+ * legacy_ht6560a - setup argument handler -+ * @unused: unused -+ * -+ * Called when the ht6560a argument is passed to this driver. This indicates -+ * that we should check all the legacy ATA addresses even if PCI is present. Should -+ * only ever be needed on very strange PCI/legacy combinations -+ */ -+ -+static int __init legacy_opti82c611a(char *unused) -+{ -+ opti82c611a = 1; -+ return 1; -+} -+ -+__setup("opti82c611a", legacy_opti82c611a); -+ -+module_init(legacy_init); -+module_exit(legacy_exit); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_mpiix.c linux-2.6.16-rc6/drivers/scsi/pata_mpiix.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_mpiix.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_mpiix.c 2006-03-10 17:06:42.000000000 +0000 -@@ -0,0 +1,303 @@ -+/* -+ * pata_mpiix.c - Intel MPIIX PATA for new ATA layer -+ * (C) 2005-2006 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * The MPIIX is different enough to the PIIX4 and friends that we give it -+ * a separate driver. The old ide/pci code handles this by just not tuning -+ * MPIIX at all. -+ * -+ * The MPIIX also differs in another important way from the majority of PIIX -+ * devices. The chip is a bridge (pardon the pun) between the old world of -+ * ISA IDE and PCI IDE. Although the ATA timings are PCI configured the actual -+ * IDE controller is not decoded in PCI space and the chip does not claim to -+ * be IDE class PCI. This requires slightly non-standard probe logic compared -+ * with PCI IDE and also that we do not disable the device when our driver is -+ * unloaded (as it has many other functions). -+ * -+ * The driver conciously keeps this logic internally to avoid pushing quirky -+ * PATA history into the clean libata layer. -+ * -+ * Thinkpad specific note: If you boot an MPIIX using thinkpad with a PCMCIA -+ * hard disk present this driver will not detect it. This is not a bug. In this -+ * configuration the secondary port of the MPIIX is disabled and the addresses -+ * are decoded by the PCMCIA bridge and therefore are for a generic IDE driver -+ * to operate. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_mpiix" -+#define DRV_VERSION "0.4.1" -+ -+/** -+ * mpiix_phy_reset - probe reset -+ * @ap: ATA port -+ * -+ * Perform the ATA probe and bus reset sequence plus specific handling -+ * for this hardware. The MPIIX has the enable bits in a different place -+ * to PIIX4 and friends. As a pure PIO device it has no cable detect -+ */ -+ -+static void mpiix_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static const struct pci_bits mpiix_enable_bits[] = { -+ { 0x6D, 1, 0x80, 0x80 }, -+ { 0x6F, 1, 0x80, 0x80 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &mpiix_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * mpiix_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. The MPIIX allows us to program the -+ * IORDY sample point (2-5 clocks), recovery 1-4 clocks and whether -+ * prefetching or iordy are used. -+ * -+ * This would get very ugly because we can only program timing for one -+ * device at a time, the other gets PIO0. Fortunately libata calls -+ * our qc_issue_prot command before a command is issued so we can -+ * flip the timings back and forth to reduce the pain. -+ */ -+ -+static void mpiix_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ int control = 0; -+ int pio = adev->pio_mode - XFER_PIO_0; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u16 idetim; -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; -+ -+ pci_read_config_word(pdev, 0x6C, &idetim); -+ /* Mask the IORDY/TIME/PPE0 bank for this device */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable for disk */ -+ if (ata_pio_need_iordy(adev)) -+ control |= 2; /* IORDY */ -+ if (pio > 0) -+ control |= 1; /* This drive is on the fast timing bank */ -+ -+ /* Mask out timing and clear both TIME bank selects */ -+ idetim &= 0xCCEE; -+ idetim &= ~(0x07 << (2 * adev->devno)); -+ idetim |= (control << (2 * adev->devno)); -+ -+ idetim |= (timings[pio][0] << 12) | (timings[pio][1] << 8); -+ pci_write_config_word(pdev, 0x6C, idetim); -+ -+ /* We use ap->private_data as a pointer to the device currently -+ loaded for timing */ -+ ap->private_data = adev; -+} -+ -+/** -+ * mpiix_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so -+ * that, even if we get this wrong, cycles to the other device will -+ * be made PIO0. -+ */ -+ -+static int mpiix_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ -+ /* If modes have been configured and the channel data is not loaded -+ then load it. We have to check if pio_mode is set as the core code -+ does not set adev->pio_mode to XFER_PIO_0 while probing as would be -+ logical */ -+ -+ if (adev->pio_mode && adev != ap->private_data) -+ mpiix_set_piomode(ap, adev); -+ -+ return ata_qc_issue_prot(qc); -+} -+ -+static struct scsi_host_template mpiix_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations mpiix_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = mpiix_set_piomode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = mpiix_phy_reset, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = mpiix_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ /* Single threaded by the PCI probe logic */ -+ static struct ata_probe_ent probe[2]; -+ static int printed_version; -+ u16 idetim; -+ int enabled; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); -+ -+ /* MPIIX has many functions which can be turned on or off according -+ to other devices present. Make sure IDE is enabled before we try -+ and use it */ -+ -+ pci_read_config_word(dev, 0x6C, &idetim); -+ if (!(idetim & 0x8000)) -+ return -ENODEV; -+ -+ /* We do our own plumbing to avoid leaking special cases for whacko -+ ancient hardware into the core code. There are two issues to -+ worry about. #1 The chip is a bridge so if in legacy mode and -+ without BARs set fools the setup. #2 If you pci_disable_device -+ the MPIIX your box goes castors up */ -+ -+ INIT_LIST_HEAD(&probe[0].node); -+ probe[0].dev = pci_dev_to_dev(dev); -+ probe[0].port_ops = &mpiix_port_ops; -+ probe[0].sht = &mpiix_sht; -+ probe[0].pio_mask = 0x1F; -+ probe[0].irq = 14; -+ probe[0].irq_flags = SA_SHIRQ; -+ probe[0].host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; -+ probe[0].legacy_mode = 1; -+ probe[0].hard_port_no = 0; -+ probe[0].n_ports = 1; -+ probe[0].port[0].cmd_addr = 0x1F0; -+ probe[0].port[0].ctl_addr = 0x3F6; -+ probe[0].port[0].altstatus_addr = 0x3F6; -+ -+ /* The secondary lurks at different addresses but is otherwise -+ the same beastie */ -+ -+ INIT_LIST_HEAD(&probe[1].node); -+ probe[1] = probe[0]; -+ probe[1].irq = 15; -+ probe[1].hard_port_no = 1; -+ probe[1].port[0].cmd_addr = 0x170; -+ probe[1].port[0].ctl_addr = 0x376; -+ probe[1].port[0].altstatus_addr = 0x376; -+ -+ /* Let libata fill in the port details */ -+ ata_std_ports(&probe[0].port[0]); -+ ata_std_ports(&probe[1].port[0]); -+ -+ /* Now add the port that is active */ -+ enabled = (idetim & 0x4000) ? 1 : 0; -+ -+ if (ata_device_add(&probe[enabled])) -+ return 0; -+ return -ENODEV; -+} -+ -+/** -+ * mpiix_remove_one - device unload -+ * @pdev: PCI device being removed -+ * -+ * Handle an unplug/unload event for a PCI device. Unload the -+ * PCI driver but do not use the default handler as we *MUST NOT* -+ * disable the device as it has other functions. -+ */ -+ -+static void __devexit mpiix_remove_one(struct pci_dev *pdev) -+{ -+ struct device *dev = pci_dev_to_dev(pdev); -+ struct ata_host_set *host_set = dev_get_drvdata(dev); -+ -+ ata_host_set_remove(host_set); -+ dev_set_drvdata(dev, NULL); -+} -+ -+ -+ -+static const struct pci_device_id mpiix[] = { -+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -+ { 0, }, -+}; -+ -+static struct pci_driver mpiix_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = mpiix, -+ .probe = mpiix_init_one, -+ .remove = mpiix_remove_one -+}; -+ -+static int __init mpiix_init(void) -+{ -+ return pci_register_driver(&mpiix_pci_driver); -+} -+ -+ -+static void __exit mpiix_exit(void) -+{ -+ pci_unregister_driver(&mpiix_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Intel MPIIX"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, mpiix); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(mpiix_init); -+module_exit(mpiix_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_netcell.c linux-2.6.16-rc6/drivers/scsi/pata_netcell.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_netcell.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_netcell.c 2006-02-08 14:05:57.000000000 +0000 -@@ -0,0 +1,176 @@ -+/* -+ * pata_netcell.c - Netcell PATA driver -+ * -+ * (c) 2006 Red Hat <alan@redhat.com> -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_netcell" -+#define DRV_VERSION "0.1" -+ -+/** -+ * netcell_cable_detect - check for 40/80 pin -+ * @ap: Port -+ * -+ * Cables are handled by the RAID controller. Report 80 pin. -+ */ -+ -+static int netcell_cable_detect(struct ata_port *ap) -+{ -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * netcell_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void netcell_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = netcell_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/* No PIO or DMA methods needed for this device */ -+ -+static struct scsi_host_template netcell_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ /* Special handling needed if you have sector or LBA48 limits */ -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ /* Use standard CHS mapping rules */ -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations netcell_ops = { -+ .port_disable = ata_port_disable, -+ -+ /* Task file is PCI ATA format, use helpers */ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = netcell_phy_reset, -+ -+ /* BMDMA handling is PCI ATA format, use helpers */ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, /* In -ac only right now */ -+ -+ /* Timeout handling. Special recovery hooks here */ -+ .eng_timeout = ata_eng_timeout, -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ /* Generic PATA PCI ATA helpers */ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+ -+/** -+ * netcell_init_one - Register Netcell ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in netcell_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ static struct ata_port_info info = { -+ .sht = &netcell_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ /* Actually we don't really care about these as the -+ firmware deals with it */ -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = 0x3f, /* UDMA 133 */ -+ .port_ops = &netcell_ops, -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ /* Any chip specific setup/optimisation/messages here */ -+ ata_pci_clear_simplex(pdev); -+ -+ /* And let the library code do the work */ -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id netcell_pci_tbl[] = { -+ { 0x169C, 0x0044, PCI_ANY_ID, PCI_ANY_ID, }, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver netcell_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = netcell_pci_tbl, -+ .probe = netcell_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init netcell_init(void) -+{ -+ return pci_register_driver(&netcell_pci_driver); -+} -+ -+static void __exit netcell_exit(void) -+{ -+ pci_unregister_driver(&netcell_pci_driver); -+} -+ -+ -+module_init(netcell_init); -+module_exit(netcell_exit); -+ -+MODULE_AUTHOR(""); -+MODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, netcell_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_ns87410.c linux-2.6.16-rc6/drivers/scsi/pata_ns87410.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_ns87410.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_ns87410.c 2006-02-15 15:05:43.000000000 +0000 -@@ -0,0 +1,213 @@ -+/* -+ * pata_ns87410.c - National Semiconductor 87410 PATA for new ATA layer -+ * (C) 2006 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_ns87410" -+#define DRV_VERSION "0.1" -+ -+/** -+ * ns87410_phy_reset - probe reset -+ * @ap: ATA port -+ * -+ * Perform the ATA probe and bus reset sequence plus specific handling -+ * for this hardware. The MPIIX has the enable bits in a different place -+ * to PIIX4 and friends. As a pure PIO device it has no cable detect -+ */ -+ -+static void ns87410_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static const struct pci_bits ns87410_enable_bits[] = { -+ { 0x43, 1, 0x08, 0x08 }, -+ { 0x47, 1, 0x08, 0x08 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &ns87410_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * ns87410_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program timing data. This is kept per channel not per device, -+ * and only affects the data port. -+ */ -+ -+static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x40 + 4 * ap->hard_port_no; -+ u8 idetcr, idefr; -+ struct ata_timing at; -+ -+ static const u8 activebits[15] = { -+ 0, 1, 2, 3, 4, -+ 5, 5, 6, 6, 6, -+ 6, 7, 7, 7, 7 -+ }; -+ -+ static const u8 recoverbits[12] = { -+ 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7 -+ }; -+ -+ pci_read_config_byte(pdev, port + 3, &idefr); -+ -+ if (ata_pio_need_iordy(adev)) -+ idefr |= 0x04; /* IORDY enable */ -+ else -+ idefr &= ~0x04; -+ -+ if (ata_timing_compute(adev, adev->pio_mode, &at, 30303, 1) < 0) { -+ dev_printk(KERN_ERR, &pdev->dev, "unknown mode %d.\n", adev->pio_mode); -+ return; -+ } -+ -+ at.active = FIT(at.active, 2, 16) - 2; -+ at.setup = FIT(at.setup, 1, 4) - 1; -+ at.recover = FIT(at.recover, 1, 12) - 1; -+ -+ idetcr = (at.setup << 6) | (recoverbits[at.recover] << 3) | activebits[at.active]; -+ -+ pci_write_config_byte(pdev, port, idetcr); -+ pci_write_config_byte(pdev, port + 3, idefr); -+ /* We use ap->private_data as a pointer to the device currently -+ loaded for timing */ -+ ap->private_data = adev; -+} -+ -+/** -+ * ns87410_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so -+ * that, even if we get this wrong, cycles to the other device will -+ * be made PIO0. -+ */ -+ -+static int ns87410_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ -+ /* If modes have been configured and the channel data is not loaded -+ then load it. We have to check if pio_mode is set as the core code -+ does not set adev->pio_mode to XFER_PIO_0 while probing as would be -+ logical */ -+ -+ if (adev->pio_mode && adev != ap->private_data) -+ ns87410_set_piomode(ap, adev); -+ -+ return ata_qc_issue_prot(qc); -+} -+ -+static struct scsi_host_template ns87410_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations ns87410_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = ns87410_set_piomode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = ns87410_phy_reset, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ns87410_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &ns87410_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x0F, -+ .port_ops = &ns87410_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = {&info, &info}; -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static const struct pci_device_id ns87410[] = { -+ { PCI_DEVICE(0x100B, 0xD001), }, -+ { 0, }, -+}; -+ -+static struct pci_driver ns87410_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = ns87410, -+ .probe = ns87410_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init ns87410_init(void) -+{ -+ return pci_register_driver(&ns87410_pci_driver); -+} -+ -+ -+static void __exit ns87410_exit(void) -+{ -+ pci_unregister_driver(&ns87410_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Nat Semi 87410"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, ns87410); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(ns87410_init); -+module_exit(ns87410_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_oldpiix.c linux-2.6.16-rc6/drivers/scsi/pata_oldpiix.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_oldpiix.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_oldpiix.c 2006-01-21 16:55:29.000000000 +0000 -@@ -0,0 +1,327 @@ -+/* -+ * pata_oldpiix.c - Intel PATA/SATA controllers -+ * -+ * (C) 2005 Red Hat <alan@redhat.com> -+ * -+ * Some parts based on ata_piix.c by Jeff Garzik and others. -+ * -+ * Early PIIX differs significantly from the later PIIX as it lacks -+ * SITRE and the slave timing registers. This means that you have to -+ * set timing per channel, or be clever. Libata tells us whenever it -+ * does drive selection and we use this to reload the timings. -+ * -+ * Because of these behaviour differences PIIX gets its own driver module. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_oldpiix" -+#define DRV_VERSION "0.3" -+ -+/** -+ * oldpiix_pata_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void oldpiix_pata_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static const struct pci_bits oldpiix_enable_bits[] = { -+ { 0x41U, 1U, 0x80UL, 0x80UL }, /* port 0 */ -+ { 0x43U, 1U, 0x80UL, 0x80UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &oldpiix_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * oldpiix_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set PIO mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void oldpiix_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio = adev->pio_mode - XFER_PIO_0; -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ unsigned int idetm_port= ap->hard_port_no ? 0x42 : 0x40; -+ u16 idetm_data; -+ int control = 0; -+ -+ /* -+ * See Intel Document 298600-004 for the timing programing rules -+ * for PIIX/ICH. Note that the early PIIX does not have the slave -+ * timing port at 0x44. -+ */ -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; -+ -+ if (pio > 2) -+ control |= 1; /* TIME1 enable */ -+ if (ata_pio_need_iordy(adev)) -+ control |= 2; /* IE IORDY */ -+ -+ /* Intel specifies that the PPE functionality is for disk only */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable */ -+ -+ pci_read_config_word(dev, idetm_port, &idetm_data); -+ -+ /* Enable PPE, IE and TIME as appropriate. Clear the other -+ drive timing bits */ -+ if (adev->devno == 0) { -+ idetm_data &= 0xCCE0; -+ idetm_data |= control; -+ } else { -+ idetm_data &= 0xCC0E; -+ idetm_data |= (control << 4); -+ } -+ idetm_data |= (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ pci_write_config_word(dev, idetm_port, idetm_data); -+ -+ /* Track which port is configured */ -+ ap->private_data = adev; -+} -+ -+/** -+ * oldpiix_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * @isich: True if the device is an ICH and has IOCFG registers -+ * -+ * Set MWDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void oldpiix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ u8 idetm_port = ap->hard_port_no ? 0x42 : 0x40; -+ u16 idetm_data; -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; -+ -+ /* -+ * MWDMA is driven by the PIO timings. We must also enable -+ * IORDY unconditionally along with TIME1. PPE has already -+ * been set when the PIO timing was set. -+ */ -+ -+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; -+ unsigned int control; -+ const unsigned int needed_pio[3] = { -+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 -+ }; -+ int pio = needed_pio[mwdma] - XFER_PIO_0; -+ -+ pci_read_config_word(dev, idetm_port, &idetm_data); -+ -+ control = 3; /* IORDY|TIME0 */ -+ /* Intel specifies that the PPE functionality is for disk only */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable */ -+ -+ /* If the drive MWDMA is faster than it can do PIO then -+ we must force PIO into PIO0 */ -+ -+ if (adev->pio_mode < needed_pio[mwdma]) -+ /* Enable DMA timing only */ -+ control |= 8; /* PIO cycles in PIO0 */ -+ -+ /* Mask out the relevant control and timing bits we will load. Also -+ clear the other drive TIME register as a precaution */ -+ if (adev->devno == 0) { -+ idetm_data &= 0xCCE0; -+ idetm_data |= control; -+ } else { -+ idetm_data &= 0xCC0E; -+ idetm_data |= (control << 4); -+ } -+ idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); -+ pci_write_config_word(dev, idetm_port, idetm_data); -+ -+ /* Track which port is configured */ -+ ap->private_data = adev; -+} -+ -+/** -+ * oldpiix_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so -+ * that, even if we get this wrong, cycles to the other device will -+ * be made PIO0. -+ */ -+ -+static int oldpiix_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ -+ if (adev != ap->private_data) { -+ if (adev->dma_mode) -+ oldpiix_set_dmamode(ap, adev); -+ else if (adev->pio_mode) -+ oldpiix_set_piomode(ap, adev); -+ } -+ return ata_qc_issue_prot(qc); -+} -+ -+ -+static struct scsi_host_template oldpiix_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations oldpiix_pata_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = oldpiix_set_piomode, -+ .set_dmamode = oldpiix_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = oldpiix_pata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = oldpiix_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+ -+/** -+ * oldpiix_init_one - Register PIIX ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in oldpiix_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. We probe for combined mode (sigh), -+ * and then hand over control to libata, for it to do the rest. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ static struct ata_port_info info = { -+ .sht = &oldpiix_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma1-2 */ -+ .port_ops = &oldpiix_pata_ops, -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id oldpiix_pci_tbl[] = { -+ { 0x8086, 0x1230, PCI_ANY_ID, PCI_ANY_ID, }, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver oldpiix_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = oldpiix_pci_tbl, -+ .probe = oldpiix_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init oldpiix_init(void) -+{ -+ return pci_register_driver(&oldpiix_pci_driver); -+} -+ -+static void __exit oldpiix_exit(void) -+{ -+ pci_unregister_driver(&oldpiix_pci_driver); -+} -+ -+ -+module_init(oldpiix_init); -+module_exit(oldpiix_exit); -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("SCSI low-level driver for early PIIX series controllers"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, oldpiix_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_opti.c linux-2.6.16-rc6/drivers/scsi/pata_opti.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_opti.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_opti.c 2006-02-16 15:38:28.000000000 +0000 -@@ -0,0 +1,268 @@ -+/* -+ * pata_opti.c - ATI PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based on -+ * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002 -+ * -+ * Copyright (C) 1996-1998 Linus Torvalds & authors (see below) -+ * -+ * Authors: -+ * Jaromir Koutek <miri@punknet.cz>, -+ * Jan Harkes <jaharkes@cwi.nl>, -+ * Mark Lord <mlord@pobox.com> -+ * Some parts of code are from ali14xx.c and from rz1000.c. -+ * -+ * Also consulted the FreeBSD prototype driver by Kevin Day to try -+ * and resolve some confusions. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_opti" -+#define DRV_VERSION "0.1.2" -+ -+enum { -+ READ_REG = 0, /* index of Read cycle timing register */ -+ WRITE_REG = 1, /* index of Write cycle timing register */ -+ CNTRL_REG = 3, /* index of Control register */ -+ STRAP_REG = 5, /* index of Strap register */ -+ MISC_REG = 6 /* index of Miscellaneous register */ -+}; -+ -+/** -+ * opti_phy_reset - probe reset -+ * @ap: ATA port -+ * -+ * Perform the ATA probe and bus reset sequence plus specific handling -+ * for this hardware. The Opti needs little handling - we have no UDMA66 -+ * capability that needs cable detection. All we must do is check the port -+ * is enabled. -+ */ -+ -+static void opti_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static const struct pci_bits opti_enable_bits[] = { -+ { 0x45, 1, 0x80, 0x00 }, -+ { 0x45, 1, 0x08, 0x00 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * opti_write_reg - control register setup -+ * @ap: ATA port -+ * @value: value -+ * @reg: control register number -+ * -+ * The Opti uses magic 'trapdoor' register accesses to do configuration -+ * rather than using PCI space as other controllers do. The double inw -+ * on the error register activates configuration mode. We can then write -+ * the control register -+ */ -+ -+static void opti_write_reg(struct ata_port *ap, u8 val, int reg) -+{ -+ unsigned long regio = ap->ioaddr.cmd_addr; -+ inw(regio + 1); -+ inw(regio + 1); -+ outb(3, regio + 2); -+ outb(val, regio + reg); -+ outb(0x83, regio + 2); -+} -+ -+#if 0 -+/** -+ * opti_read_reg - control register read -+ * @ap: ATA port -+ * @reg: control register number -+ * -+ * The Opti uses magic 'trapdoor' register accesses to do configuration -+ * rather than using PCI space as other controllers do. The double inw -+ * on the error register activates configuration mode. We can then read -+ * the control register -+ */ -+ -+static u8 opti_read_reg(struct ata_port *ap, int reg) -+{ -+ unsigned long regio = ap->ioaddr.cmd_addr; -+ u8 ret; -+ inw(regio + 1); -+ inw(regio + 1); -+ outb(3, regio + 2); -+ ret = inb(regio + reg); -+ outb(0x83, regio + 2); -+} -+#endif -+ -+/** -+ * opti_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. Timing numbers are taken from -+ * the FreeBSD driver then pre computed to keep the code clean. There -+ * are two tables depending on the hardware clock speed. -+ */ -+ -+static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ int clock; -+ int pio = adev->pio_mode - XFER_PIO_0; -+ unsigned long regio = ap->ioaddr.cmd_addr; -+ u8 addr; -+ -+ /* Address table precomputed with prefetch off and a DCLK of 2 */ -+ static const u8 addr_timing[2][5] = { -+ { 0x30, 0x20, 0x20, 0x10, 0x10 }, -+ { 0x20, 0x20, 0x10, 0x10, 0x10 } -+ }; -+ static const u8 data_rec_timing[2][5] = { -+ { 0x6B, 0x56, 0x42, 0x32, 0x31 }, -+ { 0x58, 0x44, 0x32, 0x22, 0x21 } -+ }; -+ -+ outb(0xff, regio + 5); -+ clock = inw(regio + 5) & 1; -+ -+ /* -+ * As with many controllers the address setup time is shared -+ * and must suit both devices if present. -+ */ -+ -+ addr = addr_timing[clock][pio]; -+ if (pair) { -+ /* Hardware constraint */ -+ u8 pair_addr = addr_timing[clock][pair->pio_mode - XFER_PIO_0]; -+ if (pair_addr > addr) -+ addr = pair_addr; -+ } -+ -+ /* Commence primary programming sequence */ -+ opti_write_reg(ap, adev->devno, MISC_REG); -+ opti_write_reg(ap, data_rec_timing[clock][pio], READ_REG); -+ opti_write_reg(ap, data_rec_timing[clock][pio], WRITE_REG); -+ opti_write_reg(ap, addr, MISC_REG); -+ -+ /* Programming sequence complete, override strapping */ -+ opti_write_reg(ap, 0x85, CNTRL_REG); -+} -+ -+static struct scsi_host_template opti_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations opti_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = opti_set_piomode, -+/* .set_dmamode = opti_set_dmamode, */ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = opti_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &opti_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .port_ops = &opti_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ static int printed_version; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); -+ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static const struct pci_device_id opti[] = { -+ { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { 0, }, -+}; -+ -+static struct pci_driver opti_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = opti, -+ .probe = opti_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init opti_init(void) -+{ -+ return pci_register_driver(&opti_pci_driver); -+} -+ -+ -+static void __exit opti_exit(void) -+{ -+ pci_unregister_driver(&opti_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Opti 621/621X"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, opti); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(opti_init); -+module_exit(opti_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pcmcia.c linux-2.6.16-rc6/drivers/scsi/pata_pcmcia.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pcmcia.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_pcmcia.c 2006-03-10 17:07:27.000000000 +0000 -@@ -0,0 +1,406 @@ -+/* -+ * pata-pcmcia.c - PCMCIA PATA controller driver. -+ * Copyright 2005/2006 Red Hat Inc <alan@redhat.com>, all rights reserved. -+ * -+ * Heavily based upon ide-cs.c -+ * The initial developer of the original code is David A. Hinds -+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds -+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/ata.h> -+#include <linux/libata.h> -+ -+#include <pcmcia/cs_types.h> -+#include <pcmcia/cs.h> -+#include <pcmcia/cistpl.h> -+#include <pcmcia/ds.h> -+#include <pcmcia/cisreg.h> -+#include <pcmcia/ciscode.h> -+ -+ -+#define DRV_NAME "pata_pcmcia" -+#define DRV_VERSION "0.1" -+ -+/* -+ * Private data structure to glue stuff together -+ */ -+ -+struct ata_pcmcia_info { -+ dev_link_t link; -+ int ndev; -+ dev_node_t node; -+}; -+ -+static struct scsi_host_template pcmcia_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations pcmcia_port_ops = { -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+#define CS_CHECK(fn, ret) \ -+do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -+ -+/** -+ * pcmcia_init_one - attach an pcmcia interface -+ * @pdev: pcmcia device -+ * -+ * Register a PCMCIA IDE interface. Such interfaces are PIO 0 and -+ * non shared IRQ. -+ */ -+ -+static int pcmcia_init_one(struct pcmcia_device *pdev) -+{ -+ struct ata_probe_ent ae; -+ dev_link_t *link; -+ struct ata_pcmcia_info *info; -+ client_handle_t handle; -+ tuple_t tuple; -+ struct { -+ unsigned short buf[128]; -+ cisparse_t parse; -+ config_info_t conf; -+ cistpl_cftable_entry_t dflt; -+ } *stk = NULL; -+ cistpl_cftable_entry_t *cfg; -+ int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM; -+ unsigned long io_base, ctl_base; -+ -+ info = kzalloc(sizeof(*info), GFP_KERNEL); -+ if (info == NULL) -+ return -ENOMEM; -+ -+ link = &info->link; -+ link->priv = info; -+ -+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -+ link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; -+ link->io.IOAddrLines = 3; -+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -+ link->irq.IRQInfo1 = IRQ_LEVEL_ID; -+ link->conf.Attributes = CONF_ENABLE_IRQ; -+ link->conf.Vcc = 50; -+ link->conf.IntType = INT_MEMORY_AND_IO; -+ -+ link->handle = pdev; -+ pdev->instance = link; -+ -+ handle = link->handle; -+ -+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; -+ -+ stk = kzalloc(sizeof(*stk), GFP_KERNEL); -+ if (!stk) -+ goto out1; -+ -+ cfg = &stk->parse.cftable_entry; -+ -+ tuple.TupleData = (cisdata_t *)&stk->buf; -+ tuple.TupleOffset = 0; -+ tuple.TupleDataMax = 255; -+ tuple.Attributes = 0; -+ tuple.DesiredTuple = CISTPL_CONFIG; -+ -+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); -+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); -+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); -+ link->conf.ConfigBase = stk->parse.config.base; -+ link->conf.Present = stk->parse.config.rmask[0]; -+ -+ tuple.DesiredTuple = CISTPL_MANFID; -+ if (!pcmcia_get_first_tuple(handle, &tuple) && !pcmcia_get_tuple_data(handle, &tuple) && !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) -+ is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); -+ -+ /* Configure card */ -+ link->state |= DEV_CONFIG; -+ -+ /* Not sure if this is right... look up the current Vcc */ -+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); -+ link->conf.Vcc = stk->conf.Vcc; -+ -+ pass = io_base = ctl_base = 0; -+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -+ tuple.Attributes = 0; -+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); -+ -+ while (1) { -+ if (pcmcia_get_tuple_data(handle, &tuple) != 0) -+ goto next_entry; -+ if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) -+ goto next_entry; -+ /* Check for matching Vcc, unless we're desperate */ -+ if (!pass) { -+ if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { -+ if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) -+ goto next_entry; -+ } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { -+ if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) -+ goto next_entry; -+ } -+ } -+ -+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) -+ link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; -+ else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) -+ link->conf.Vpp1 = link->conf.Vpp2 = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; -+ -+ if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { -+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io; -+ link->conf.ConfigIndex = cfg->index; -+ link->io.BasePort1 = io->win[0].base; -+ link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -+ if (!(io->flags & CISTPL_IO_16BIT)) -+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -+ if (io->nwin == 2) { -+ link->io.NumPorts1 = 8; -+ link->io.BasePort2 = io->win[1].base; -+ link->io.NumPorts2 = (is_kme) ? 2 : 1; -+ if (pcmcia_request_io(link->handle, &link->io) != 0) -+ goto next_entry; -+ io_base = link->io.BasePort1; -+ ctl_base = link->io.BasePort2; -+ } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { -+ link->io.NumPorts1 = io->win[0].len; -+ link->io.NumPorts2 = 0; -+ if (pcmcia_request_io(link->handle, &link->io) != 0) -+ goto next_entry; -+ io_base = link->io.BasePort1; -+ ctl_base = link->io.BasePort1 + 0x0e; -+ } else goto next_entry; -+ /* If we've got this far, we're done */ -+ break; -+ } -+next_entry: -+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -+ memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); -+ if (pass) { -+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); -+ } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { -+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); -+ memset(&stk->dflt, 0, sizeof(stk->dflt)); -+ pass++; -+ } -+ } -+ -+ if (is_kme) -+ outb(0x81, ctl_base + 0x01); -+ -+ /* FIXME: Could be more ports at base + 0x10 but we only deal with -+ one right now */ -+ -+ if (link->io.NumPorts1 >= 0x20) -+ printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n"); -+ -+ /* -+ * Having done the PCMCIA plumbing the ATA side is relatively -+ * sane. -+ */ -+ -+ memset(&ae, 0, sizeof(struct ata_probe_ent)); -+ INIT_LIST_HEAD(&ae.node); -+ ae.dev = &pdev->dev; -+ ae.port_ops = &pcmcia_port_ops; -+ ae.sht = &pcmcia_sht; -+ ae.n_ports = 1; -+ ae.pio_mask = 1; /* ISA so PIO 0 cycles */ -+ ae.irq = link->irq.AssignedIRQ; -+ ae.irq_flags = 0; -+ ae.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IRQ_MASK | ATA_FLAG_SRST; -+ ae.port[0].cmd_addr = io_base; -+ ae.port[0].altstatus_addr = ctl_base; -+ ae.port[0].ctl_addr = ctl_base; -+ ata_std_ports(&ae.port[0]); -+ -+ if (ata_device_add(&ae) == 0) -+ goto failed; -+ -+ info->ndev = 1; -+ link->dev = &info->node; -+ link->state &= ~DEV_CONFIG_PENDING; -+ kfree(stk); -+ return 0; -+ -+cs_failed: -+ cs_error(link->handle, last_fn, last_ret); -+failed: -+ kfree(stk); -+ info->ndev = 0; -+ link->dev = NULL; -+ -+ pcmcia_release_configuration(link->handle); -+ pcmcia_release_io(link->handle, &link->io); -+ pcmcia_release_irq(link->handle, &link->irq); -+ -+ link->state &= ~DEV_CONFIG; -+out1: -+ kfree(info); -+ return ret; -+} -+ -+/** -+ * pcmcia_remove_one - unplug an pcmcia interface -+ * @pdev: pcmcia device -+ * -+ * A PCMCIA ATA device has been unplugged. Perform the needed -+ * cleanup. Also called on module unload for any active devices. -+ */ -+ -+void pcmcia_remove_one(struct pcmcia_device *pdev) -+{ -+ dev_link_t *link = dev_to_instance(pdev); -+ struct ata_pcmcia_info *info = link->priv; -+ struct device *dev = &pdev->dev; -+ -+ if (link->state & DEV_CONFIG) { -+ if (info->ndev) { -+ struct ata_host_set *host_set = dev_get_drvdata(dev); -+ ata_host_set_remove(host_set); -+ dev_set_drvdata(dev, NULL); -+ } -+ info->ndev = 0; -+ link->dev = NULL; -+ -+ pcmcia_release_configuration(link->handle); -+ pcmcia_release_io(link->handle, &link->io); -+ pcmcia_release_irq(link->handle, &link->irq); -+ link->state &= ~DEV_CONFIG; -+ } -+ kfree(link->priv); -+} -+ -+static int pcmcia_suspend(struct pcmcia_device *dev) -+{ -+ dev_link_t *link = dev_to_instance(dev); -+ -+ link->state |= DEV_SUSPEND; -+ if (link->state & DEV_CONFIG) -+ pcmcia_release_configuration(link->handle); -+ -+ return 0; -+} -+ -+static int pcmcia_resume(struct pcmcia_device *dev) -+{ -+ dev_link_t *link = dev_to_instance(dev); -+ -+ link->state &= ~DEV_SUSPEND; -+ if (DEV_OK(link)) -+ pcmcia_request_configuration(link->handle, &link->conf); -+ -+ return 0; -+} -+ -+static struct pcmcia_device_id pcmcia_devices[] = { -+ PCMCIA_DEVICE_FUNC_ID(4), -+ PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */ -+ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), -+ PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), -+ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ -+ PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), -+ PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ -+ PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */ -+ PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), -+ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */ -+ PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), -+ PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74), -+ PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), -+ PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), -+ PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), -+ PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), -+ PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), -+ PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), -+ PCMCIA_DEVICE_PROD_ID12("EXP", "CD+GAME", 0x6f58c983, 0x63c13aaf), -+ PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), -+ PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), -+ PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), -+ PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae), -+ PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178), -+ PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), -+ PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), -+ PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), -+ PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), -+ PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), -+ PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), -+ PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), -+ PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), -+ PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), -+ PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), -+ PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), -+ PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), -+ PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), -+ PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), -+ PCMCIA_DEVICE_NULL, -+}; -+ -+MODULE_DEVICE_TABLE(pcmcia, pcmcia_devices); -+ -+static struct pcmcia_driver pcmcia_driver = { -+ .owner = THIS_MODULE, -+ .drv = { -+ .name = DRV_NAME, -+ }, -+ .id_table = pcmcia_devices, -+ .probe = pcmcia_init_one, -+ .remove = pcmcia_remove_one, -+ .suspend = pcmcia_suspend, -+ .resume = pcmcia_resume, -+}; -+ -+static int __init pcmcia_init(void) -+{ -+ return pcmcia_register_driver(&pcmcia_driver); -+} -+ -+static void __exit pcmcia_exit(void) -+{ -+ pcmcia_unregister_driver(&pcmcia_driver); -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for PCMCIA ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(pcmcia_init); -+module_exit(pcmcia_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pdc2027x.c linux-2.6.16-rc6/drivers/scsi/pata_pdc2027x.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pdc2027x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_pdc2027x.c 2006-01-21 16:56:47.000000000 +0000 -@@ -0,0 +1,857 @@ -+/* -+ * Promise PATA TX2/TX4/TX2000/133 IDE driver for pdc20268 to pdc20277. -+ * -+ * 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. -+ * -+ * Ported to libata by: -+ * Albert Lee <albertcc@tw.ibm.com> IBM Corporation -+ * -+ * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> -+ * Portions Copyright (C) 1999 Promise Technology, Inc. -+ * -+ * Author: Frank Tiernan (frankt@promise.com) -+ * Released under terms of General Public License -+ * -+ * -+ * libata documentation is available via 'make {ps|pdf}docs', -+ * as Documentation/DocBook/libata.* -+ * -+ * Hardware information only available under NDA. -+ * -+ */ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi.h> -+#include <scsi/scsi_host.h> -+#include <scsi/scsi_cmnd.h> -+#include <linux/libata.h> -+#include <asm/io.h> -+ -+#define DRV_NAME "pata_pdc2027x" -+#define DRV_VERSION "0.73" -+#undef PDC_DEBUG -+ -+#ifdef PDC_DEBUG -+#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) -+#else -+#define PDPRINTK(fmt, args...) -+#endif -+ -+enum { -+ PDC_UDMA_100 = 0, -+ PDC_UDMA_133 = 1, -+ -+ PDC_100_MHZ = 100000000, -+ PDC_133_MHZ = 133333333, -+ -+ PDC_SYS_CTL = 0x1100, -+ PDC_ATA_CTL = 0x1104, -+ PDC_GLOBAL_CTL = 0x1108, -+ PDC_CTCR0 = 0x110C, -+ PDC_CTCR1 = 0x1110, -+ PDC_BYTE_COUNT = 0x1120, -+ PDC_PLL_CTL = 0x1202, -+}; -+ -+static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -+static void pdc2027x_remove_one(struct pci_dev *pdev); -+static void pdc2027x_phy_reset(struct ata_port *ap); -+static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev); -+static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev); -+static void pdc2027x_post_set_mode(struct ata_port *ap); -+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc); -+ -+/* -+ * ATA Timing Tables based on 133MHz controller clock. -+ * These tables are only used when the controller is in 133MHz clock. -+ * If the controller is in 100MHz clock, the ASIC hardware will -+ * set the timing registers automatically when "set feature" command -+ * is issued to the device. However, if the controller clock is 133MHz, -+ * the following tables must be used. -+ */ -+static struct pdc2027x_pio_timing { -+ u8 value0, value1, value2; -+} pdc2027x_pio_timing_tbl [] = { -+ { 0xfb, 0x2b, 0xac }, /* PIO mode 0 */ -+ { 0x46, 0x29, 0xa4 }, /* PIO mode 1 */ -+ { 0x23, 0x26, 0x64 }, /* PIO mode 2 */ -+ { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ -+ { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ -+}; -+ -+static struct pdc2027x_mdma_timing { -+ u8 value0, value1; -+} pdc2027x_mdma_timing_tbl [] = { -+ { 0xdf, 0x5f }, /* MDMA mode 0 */ -+ { 0x6b, 0x27 }, /* MDMA mode 1 */ -+ { 0x69, 0x25 }, /* MDMA mode 2 */ -+}; -+ -+static struct pdc2027x_udma_timing { -+ u8 value0, value1, value2; -+} pdc2027x_udma_timing_tbl [] = { -+ { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ -+ { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ -+ { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ -+ { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ -+ { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ -+ { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ -+ { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ -+}; -+ -+static const struct pci_device_id pdc2027x_pci_tbl[] = { -+#ifdef ATA_ENABLE_PATA -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20270, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_100 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20277, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PDC_UDMA_133 }, -+#endif -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver pdc2027x_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pdc2027x_pci_tbl, -+ .probe = pdc2027x_init_one, -+ .remove = __devexit_p(pdc2027x_remove_one), -+}; -+ -+static struct scsi_host_template pdc2027x_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+}; -+ -+static struct ata_port_operations pdc2027x_pata100_ops = { -+ .port_disable = ata_port_disable, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = pdc2027x_phy_reset, -+ -+ .check_atapi_dma = pdc2027x_check_atapi_dma, -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_mmio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static struct ata_port_operations pdc2027x_pata133_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = pdc2027x_set_piomode, -+ .set_dmamode = pdc2027x_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = pdc2027x_phy_reset, -+ .post_set_mode = pdc2027x_post_set_mode, -+ -+ .check_atapi_dma = pdc2027x_check_atapi_dma, -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_mmio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static struct ata_port_info pdc2027x_port_info[] = { -+ /* PDC_UDMA_100 */ -+ { -+ .sht = &pdc2027x_sht, -+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | -+ ATA_FLAG_SRST | ATA_FLAG_MMIO, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = ATA_UDMA5, /* udma0-5 */ -+ .port_ops = &pdc2027x_pata100_ops, -+ }, -+ /* PDC_UDMA_133 */ -+ { -+ .sht = &pdc2027x_sht, -+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | -+ ATA_FLAG_SRST | ATA_FLAG_MMIO, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma0-2 */ -+ .udma_mask = ATA_UDMA6, /* udma0-6 */ -+ .port_ops = &pdc2027x_pata133_ops, -+ }, -+}; -+ -+MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Albert Lee"); -+MODULE_DESCRIPTION("libata driver module for Promise PDC20268 to PDC20277"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+MODULE_DEVICE_TABLE(pci, pdc2027x_pci_tbl); -+ -+/** -+ * port_mmio - Get the MMIO address of PDC2027x extended registers -+ * @ap: Port -+ * @offset: offset from mmio base -+ */ -+static inline void* port_mmio(struct ata_port *ap, unsigned int offset) -+{ -+ return ap->host_set->mmio_base + ap->port_no * 0x100 + offset; -+} -+ -+/** -+ * dev_mmio - Get the MMIO address of PDC2027x extended registers -+ * @ap: Port -+ * @adev: device -+ * @offset: offset from mmio base -+ */ -+static inline void* dev_mmio(struct ata_port *ap, struct ata_device *adev, unsigned int offset) -+{ -+ u8 adj = (adev->devno) ? 0x08 : 0x00; -+ return port_mmio(ap, offset) + adj; -+} -+ -+/** -+ * pdc2027x_pata_cbl_detect - Probe host controller cable detect info -+ * @ap: Port for which cable detect info is desired -+ * -+ * Read 80c cable indicator from Promise extended register. -+ * This register is latched when the system is reset. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+static void pdc2027x_cbl_detect(struct ata_port *ap) -+{ -+ u32 cgcr; -+ -+ /* check cable detect results */ -+ cgcr = readl(port_mmio(ap, PDC_GLOBAL_CTL)); -+ if (cgcr & (1 << 26)) -+ goto cbl40; -+ -+ PDPRINTK("No cable or 80-conductor cable on port %d\n", ap->port_no); -+ -+ ap->cbl = ATA_CBL_PATA80; -+ return; -+ -+cbl40: -+ printk(KERN_INFO DRV_NAME ": 40-conductor cable detected on port %d\n", ap->port_no); -+ ap->cbl = ATA_CBL_PATA40; -+ ap->udma_mask &= ATA_UDMA_MASK_40C; -+} -+ -+/** -+ * pdc2027x_port_enabled - Check PDC ATA control register to see whether the port is enabled. -+ * @ap: Port to check -+ */ -+static inline int pdc2027x_port_enabled(struct ata_port *ap) -+{ -+ return readb(port_mmio(ap, PDC_ATA_CTL)) & 0x02; -+} -+ -+/** -+ * pdc2027x_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * Probe PATA phy. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+static void pdc2027x_phy_reset(struct ata_port *ap) -+{ -+ /* Check whether port enabled */ -+ if (!pdc2027x_port_enabled(ap)) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ -+ pdc2027x_cbl_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * pdc2027x_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port to configure -+ * @adev: um -+ * @pio: PIO mode, 0 - 4 -+ * -+ * Set PIO mode for device. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio = adev->pio_mode - XFER_PIO_0; -+ u32 ctcr0, ctcr1; -+ -+ PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode); -+ -+ /* Sanity check */ -+ if (pio > 4) { -+ printk(KERN_ERR DRV_NAME ": Unknown pio mode [%d] ignored\n", pio); -+ return; -+ -+ } -+ -+ /* Set the PIO timing registers using value table for 133MHz */ -+ PDPRINTK("Set pio regs... \n"); -+ -+ ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); -+ ctcr0 &= 0xffff0000; -+ ctcr0 |= pdc2027x_pio_timing_tbl[pio].value0 | -+ (pdc2027x_pio_timing_tbl[pio].value1 << 8); -+ writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); -+ -+ ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); -+ ctcr1 &= 0x00ffffff; -+ ctcr1 |= (pdc2027x_pio_timing_tbl[pio].value2 << 24); -+ writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); -+ -+ PDPRINTK("Set pio regs done\n"); -+ -+ PDPRINTK("Set to pio mode[%u] \n", pio); -+} -+ -+/** -+ * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings -+ * @ap: Port to configure -+ * @adev: um -+ * @udma: udma mode, XFER_UDMA_0 to XFER_UDMA_6 -+ * -+ * Set UDMA mode for device. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int dma_mode = adev->dma_mode; -+ u32 ctcr0, ctcr1; -+ -+ if ((dma_mode >= XFER_UDMA_0) && -+ (dma_mode <= XFER_UDMA_6)) { -+ /* Set the UDMA timing registers with value table for 133MHz */ -+ unsigned int udma_mode = dma_mode & 0x07; -+ -+ if (dma_mode == XFER_UDMA_2) { -+ /* -+ * Turn off tHOLD. -+ * If tHOLD is '1', the hardware will add half clock for data hold time. -+ * This code segment seems to be no effect. tHOLD will be overwritten below. -+ */ -+ ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); -+ writel(ctcr1 & ~(1 << 7), dev_mmio(ap, adev, PDC_CTCR1)); -+ } -+ -+ PDPRINTK("Set udma regs... \n"); -+ -+ ctcr1 = readl(dev_mmio(ap, adev, PDC_CTCR1)); -+ ctcr1 &= 0xff000000; -+ ctcr1 |= pdc2027x_udma_timing_tbl[udma_mode].value0 | -+ (pdc2027x_udma_timing_tbl[udma_mode].value1 << 8) | -+ (pdc2027x_udma_timing_tbl[udma_mode].value2 << 16); -+ writel(ctcr1, dev_mmio(ap, adev, PDC_CTCR1)); -+ -+ PDPRINTK("Set udma regs done\n"); -+ -+ PDPRINTK("Set to udma mode[%u] \n", udma_mode); -+ -+ } else if ((dma_mode >= XFER_MW_DMA_0) && -+ (dma_mode <= XFER_MW_DMA_2)) { -+ /* Set the MDMA timing registers with value table for 133MHz */ -+ unsigned int mdma_mode = dma_mode & 0x07; -+ -+ PDPRINTK("Set mdma regs... \n"); -+ ctcr0 = readl(dev_mmio(ap, adev, PDC_CTCR0)); -+ -+ ctcr0 &= 0x0000ffff; -+ ctcr0 |= (pdc2027x_mdma_timing_tbl[mdma_mode].value0 << 16) | -+ (pdc2027x_mdma_timing_tbl[mdma_mode].value1 << 24); -+ -+ writel(ctcr0, dev_mmio(ap, adev, PDC_CTCR0)); -+ PDPRINTK("Set mdma regs done\n"); -+ -+ PDPRINTK("Set to mdma mode[%u] \n", mdma_mode); -+ } else { -+ printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode); -+ } -+} -+ -+/** -+ * pdc2027x_post_set_mode - Set the timing registers back to correct values. -+ * @ap: Port to configure -+ * -+ * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers -+ * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL. -+ * This function overwrites the possibly incorrect values set by the hardware to be correct. -+ */ -+static void pdc2027x_post_set_mode(struct ata_port *ap) -+{ -+ int i; -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ -+ if (ata_dev_present(dev)) { -+ -+ pdc2027x_set_piomode(ap, dev); -+ -+ /* -+ * Enable prefetch if the device support PIO only. -+ */ -+ if (dev->xfer_shift == ATA_SHIFT_PIO) { -+ u32 ctcr1 = readl(dev_mmio(ap, dev, PDC_CTCR1)); -+ ctcr1 |= (1 << 25); -+ writel(ctcr1, dev_mmio(ap, dev, PDC_CTCR1)); -+ -+ PDPRINTK("Turn on prefetch\n"); -+ } else { -+ pdc2027x_set_dmamode(ap, dev); -+ } -+ } -+ } -+} -+ -+/** -+ * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command -+ * @qc: Metadata associated with taskfile to check -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ * -+ * RETURNS: 0 when ATAPI DMA can be used -+ * 1 otherwise -+ */ -+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc) -+{ -+ struct scsi_cmnd *cmd = qc->scsicmd; -+ u8 *scsicmd = cmd->cmnd; -+ int rc = 1; /* atapi dma off by default */ -+ -+ /* -+ * This workaround is from Promise's GPL driver. -+ * If ATAPI DMA is used for commands not in the -+ * following white list, say MODE_SENSE and REQUEST_SENSE, -+ * pdc2027x might hit the irq lost problem. -+ */ -+ switch (scsicmd[0]) { -+ case READ_10: -+ case WRITE_10: -+ case READ_12: -+ case WRITE_12: -+ case READ_6: -+ case WRITE_6: -+ case 0xad: /* READ_DVD_STRUCTURE */ -+ case 0xbe: /* READ_CD */ -+ /* ATAPI DMA is ok */ -+ rc = 0; -+ break; -+ default: -+ ; -+ } -+ -+ return rc; -+} -+ -+/** -+ * pdc_read_counter - Read the ctr counter -+ * @probe_ent: for the port address -+ */ -+ -+static long pdc_read_counter(struct ata_probe_ent *probe_ent) -+{ -+ long counter; -+ int retry = 1; -+ u32 bccrl, bccrh, bccrlv, bccrhv; -+ -+retry: -+ bccrl = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; -+ bccrh = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; -+ rmb(); -+ -+ /* Read the counter values again for verification */ -+ bccrlv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT) & 0xffff; -+ bccrhv = readl(probe_ent->mmio_base + PDC_BYTE_COUNT + 0x100) & 0xffff; -+ rmb(); -+ -+ counter = (bccrh << 15) | bccrl; -+ -+ PDPRINTK("bccrh [%X] bccrl [%X]\n", bccrh, bccrl); -+ PDPRINTK("bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv); -+ -+ /* -+ * The 30-bit decreasing counter are read by 2 pieces. -+ * Incorrect value may be read when both bccrh and bccrl are changing. -+ * Ex. When 7900 decrease to 78FF, wrong value 7800 might be read. -+ */ -+ if (retry && !(bccrh == bccrhv && bccrl >= bccrlv)) { -+ retry--; -+ PDPRINTK("rereading counter\n"); -+ goto retry; -+ } -+ -+ return counter; -+} -+ -+/** -+ * adjust_pll - Adjust the PLL input clock in Hz. -+ * -+ * @pdc_controller: controller specific information -+ * @probe_ent: For the port address -+ * @pll_clock: The input of PLL in HZ -+ */ -+static void pdc_adjust_pll(struct ata_probe_ent *probe_ent, long pll_clock, unsigned int board_idx) -+{ -+ -+ u16 pll_ctl; -+ long pll_clock_khz = pll_clock / 1000; -+ long pout_required = board_idx? PDC_133_MHZ:PDC_100_MHZ; -+ long ratio = pout_required / pll_clock_khz; -+ int F, R; -+ -+ /* Sanity check */ -+ if (unlikely(pll_clock_khz < 5000L || pll_clock_khz > 70000L)) { -+ printk(KERN_ERR DRV_NAME ": Invalid PLL input clock %ldkHz, give up!\n", pll_clock_khz); -+ return; -+ } -+ -+#ifdef PDC_DEBUG -+ PDPRINTK("pout_required is %ld\n", pout_required); -+ -+ /* Show the current clock value of PLL control register -+ * (maybe already configured by the firmware) -+ */ -+ pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); -+ -+ PDPRINTK("pll_ctl[%X]\n", pll_ctl); -+#endif -+ -+ /* -+ * Calculate the ratio of F, R and OD -+ * POUT = (F + 2) / (( R + 2) * NO) -+ */ -+ if (ratio < 8600L) { /* 8.6x */ -+ /* Using NO = 0x01, R = 0x0D */ -+ R = 0x0d; -+ } else if (ratio < 12900L) { /* 12.9x */ -+ /* Using NO = 0x01, R = 0x08 */ -+ R = 0x08; -+ } else if (ratio < 16100L) { /* 16.1x */ -+ /* Using NO = 0x01, R = 0x06 */ -+ R = 0x06; -+ } else if (ratio < 64000L) { /* 64x */ -+ R = 0x00; -+ } else { -+ /* Invalid ratio */ -+ printk(KERN_ERR DRV_NAME ": Invalid ratio %ld, give up!\n", ratio); -+ return; -+ } -+ -+ F = (ratio * (R+2)) / 1000 - 2; -+ -+ if (unlikely(F < 0 || F > 127)) { -+ /* Invalid F */ -+ printk(KERN_ERR DRV_NAME ": F[%d] invalid!\n", F); -+ return; -+ } -+ -+ PDPRINTK("F[%d] R[%d] ratio*1000[%ld]\n", F, R, ratio); -+ -+ pll_ctl = (R << 8) | F; -+ -+ PDPRINTK("Writing pll_ctl[%X]\n", pll_ctl); -+ -+ writew(pll_ctl, probe_ent->mmio_base + PDC_PLL_CTL); -+ readw(probe_ent->mmio_base + PDC_PLL_CTL); /* flush */ -+ -+ /* Wait the PLL circuit to be stable */ -+ mdelay(30); -+ -+#ifdef PDC_DEBUG -+ /* -+ * Show the current clock value of PLL control register -+ * (maybe configured by the firmware) -+ */ -+ pll_ctl = readw(probe_ent->mmio_base + PDC_PLL_CTL); -+ -+ PDPRINTK("pll_ctl[%X]\n", pll_ctl); -+#endif -+ -+ return; -+} -+ -+/** -+ * detect_pll_input_clock - Detect the PLL input clock in Hz. -+ * @probe_ent: for the port address -+ * Ex. 16949000 on 33MHz PCI bus for pdc20275. -+ * Half of the PCI clock. -+ */ -+static long pdc_detect_pll_input_clock(struct ata_probe_ent *probe_ent) -+{ -+ u32 scr; -+ long start_count, end_count; -+ long pll_clock; -+ -+ /* Read current counter value */ -+ start_count = pdc_read_counter(probe_ent); -+ -+ /* Start the test mode */ -+ scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); -+ PDPRINTK("scr[%X]\n", scr); -+ writel(scr | (0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); -+ readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ -+ -+ /* Let the counter run for 100 ms. */ -+ mdelay(100); -+ -+ /* Read the counter values again */ -+ end_count = pdc_read_counter(probe_ent); -+ -+ /* Stop the test mode */ -+ scr = readl(probe_ent->mmio_base + PDC_SYS_CTL); -+ PDPRINTK("scr[%X]\n", scr); -+ writel(scr & ~(0x01 << 14), probe_ent->mmio_base + PDC_SYS_CTL); -+ readl(probe_ent->mmio_base + PDC_SYS_CTL); /* flush */ -+ -+ /* calculate the input clock in Hz */ -+ pll_clock = (start_count - end_count) * 10; -+ -+ PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count); -+ PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock); -+ -+ return pll_clock; -+} -+ -+/** -+ * pdc_hardware_init - Initialize the hardware. -+ * @pdev: instance of pci_dev found -+ * @pdc_controller: controller specific information -+ * @pe: for the port address -+ */ -+static int pdc_hardware_init(struct pci_dev *pdev, struct ata_probe_ent *pe, unsigned int board_idx) -+{ -+ long pll_clock; -+ -+ /* -+ * Detect PLL input clock rate. -+ * On some system, where PCI bus is running at non-standard clock rate. -+ * Ex. 25MHz or 40MHz, we have to adjust the cycle_time. -+ * The pdc20275 controller employs PLL circuit to help correct timing registers setting. -+ */ -+ pll_clock = pdc_detect_pll_input_clock(pe); -+ -+ if (pll_clock < 0) /* counter overflow? Try again. */ -+ pll_clock = pdc_detect_pll_input_clock(pe); -+ -+ dev_printk(KERN_INFO, &pdev->dev, "PLL input clock %ld kHz\n", pll_clock/1000); -+ -+ /* Adjust PLL control register */ -+ pdc_adjust_pll(pe, pll_clock, board_idx); -+ -+ return 0; -+} -+ -+/** -+ * pdc_ata_setup_port - setup the mmio address -+ * @port: ata ioports to setup -+ * @base: base address -+ */ -+static void pdc_ata_setup_port(struct ata_ioports *port, unsigned long base) -+{ -+ port->cmd_addr = -+ port->data_addr = base; -+ port->feature_addr = -+ port->error_addr = base + 0x05; -+ port->nsect_addr = base + 0x0a; -+ port->lbal_addr = base + 0x0f; -+ port->lbam_addr = base + 0x10; -+ port->lbah_addr = base + 0x15; -+ port->device_addr = base + 0x1a; -+ port->command_addr = -+ port->status_addr = base + 0x1f; -+ port->altstatus_addr = -+ port->ctl_addr = base + 0x81a; -+} -+ -+/** -+ * pdc2027x_init_one - PCI probe function -+ * Called when an instance of PCI adapter is inserted. -+ * This function checks whether the hardware is supported, -+ * initialize hardware and register an instance of ata_host_set to -+ * libata by providing struct ata_probe_ent and ata_device_add(). -+ * (implements struct pci_driver.probe() ) -+ * -+ * @pdev: instance of pci_dev found -+ * @ent: matching entry in the id_tbl[] -+ */ -+static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ unsigned int board_idx = (unsigned int) ent->driver_data; -+ -+ struct ata_probe_ent *probe_ent = NULL; -+ unsigned long base; -+ void *mmio_base; -+ int rc; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); -+ -+ rc = pci_enable_device(pdev); -+ if (rc) -+ return rc; -+ -+ rc = pci_request_regions(pdev, DRV_NAME); -+ if (rc) -+ goto err_out; -+ -+ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); -+ if (rc) -+ goto err_out_regions; -+ -+ rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); -+ if (rc) -+ goto err_out_regions; -+ -+ /* Prepare the probe entry */ -+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); -+ if (probe_ent == NULL) { -+ rc = -ENOMEM; -+ goto err_out_regions; -+ } -+ -+ memset(probe_ent, 0, sizeof(*probe_ent)); -+ probe_ent->dev = pci_dev_to_dev(pdev); -+ INIT_LIST_HEAD(&probe_ent->node); -+ -+ mmio_base = ioremap(pci_resource_start(pdev, 5), -+ pci_resource_len(pdev, 5)); -+ -+ if (mmio_base == NULL) { -+ rc = -ENOMEM; -+ goto err_out_free_ent; -+ } -+ -+ base = (unsigned long) mmio_base; -+ -+ probe_ent->sht = pdc2027x_port_info[board_idx].sht; -+ probe_ent->host_flags = pdc2027x_port_info[board_idx].host_flags; -+ probe_ent->pio_mask = pdc2027x_port_info[board_idx].pio_mask; -+ probe_ent->mwdma_mask = pdc2027x_port_info[board_idx].mwdma_mask; -+ probe_ent->udma_mask = pdc2027x_port_info[board_idx].udma_mask; -+ probe_ent->port_ops = pdc2027x_port_info[board_idx].port_ops; -+ -+ probe_ent->irq = pdev->irq; -+ probe_ent->irq_flags = SA_SHIRQ; -+ probe_ent->mmio_base = mmio_base; -+ -+ pdc_ata_setup_port(&probe_ent->port[0], base + 0x17c0); -+ probe_ent->port[0].bmdma_addr = base + 0x1000; -+ pdc_ata_setup_port(&probe_ent->port[1], base + 0x15c0); -+ probe_ent->port[1].bmdma_addr = base + 0x1008; -+ -+ probe_ent->n_ports = 2; -+ -+ pci_set_master(pdev); -+ //pci_enable_intx(pdev); -+ -+ /* initialize adapter */ -+ if (pdc_hardware_init(pdev, probe_ent, board_idx) != 0) -+ goto err_out_free_ent; -+ -+ ata_device_add(probe_ent); -+ kfree(probe_ent); -+ -+ return 0; -+ -+err_out_free_ent: -+ kfree(probe_ent); -+err_out_regions: -+ pci_release_regions(pdev); -+err_out: -+ pci_disable_device(pdev); -+ return rc; -+} -+ -+/** -+ * pdc2027x_remove_one - Called to remove a single instance of the -+ * adapter. -+ * -+ * @dev: The PCI device to remove. -+ * FIXME: module load/unload not working yet -+ */ -+static void __devexit pdc2027x_remove_one(struct pci_dev *pdev) -+{ -+ ata_pci_remove_one(pdev); -+} -+ -+/** -+ * pdc2027x_init - Called after this module is loaded into the kernel. -+ */ -+static int __init pdc2027x_init(void) -+{ -+ return pci_register_driver(&pdc2027x_pci_driver); -+} -+ -+/** -+ * pdc2027x_exit - Called before this module unloaded from the kernel -+ */ -+static void __exit pdc2027x_exit(void) -+{ -+ pci_unregister_driver(&pdc2027x_pci_driver); -+} -+ -+module_init(pdc2027x_init); -+module_exit(pdc2027x_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pdc202xx_old.c linux-2.6.16-rc6/drivers/scsi/pata_pdc202xx_old.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_pdc202xx_old.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_pdc202xx_old.c 2006-02-20 13:19:57.000000000 +0000 -@@ -0,0 +1,428 @@ -+/* -+ * pata_pdc202xx_old.c - SL82C105 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based in part on linux/drivers/ide/pci/pdc202xx_old.c -+ * -+ * Initial revision -+ * -+ * TODO: -+ * Channel interlock/reset on both required ? -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_pdc202xx_old" -+#define DRV_VERSION "0.1.2" -+ -+static void pdc2024x_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+ -+static void pdc2026x_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u16 cis; -+ -+ pci_read_config_word(pdev, 0x50, &cis); -+ if (cis & (1 << (10 + ap->hard_port_no))) -+ ap->cbl = ATA_CBL_PATA80; -+ else -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+ -+/** -+ * pdc_configure_piomode - set chip PIO timing -+ * @ap: ATA interface -+ * @adev: ATA device -+ * @pio: PIO mode -+ * -+ * Called to do the PIO mode setup. Our timing registers are shared -+ * so a configure_dmamode call will undo any work we do here and vice -+ * versa -+ */ -+ -+static void pdc_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x60 + 4 * ap->hard_port_no + 2 * adev->devno; -+ static u16 pio_timing[5] = { -+ 0x0913, 0x050C , 0x0308, 0x0206, 0x0104 -+ }; -+ u8 r_ap, r_bp; -+ -+ /* FIFO, IORDY ? */ -+ pci_read_config_byte(pdev, port, &r_ap); -+ pci_read_config_byte(pdev, port + 1, &r_bp); -+ r_ap &= ~0x0F; -+ r_bp &= ~0x07; -+ r_ap |= (pio_timing[pio] >> 8); -+ r_bp |= (pio_timing[pio] & 0xFF); -+ pci_write_config_byte(pdev, port, r_ap); -+ pci_write_config_byte(pdev, port + 1, r_bp); -+} -+ -+/** -+ * pdc_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. Our timing registers are shared -+ * but we want to set the PIO timing by default. -+ */ -+ -+static void pdc_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ pdc_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -+} -+ -+/** -+ * pdc_configure_dmamode - set DMA mode in chip -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Load DMA cycle times into the chip ready for a DMA transfer -+ * to occur. -+ */ -+ -+static void pdc_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x60 + 4 * ap->hard_port_no + 2 * adev->devno; -+ static u8 udma_timing[6][2] = { -+ { 0x60, 0x03 }, /* 33 Mhz Clock */ -+ { 0x40, 0x02 }, -+ { 0x20, 0x01 }, -+ { 0x40, 0x02 }, /* 66 Mhz Clock */ -+ { 0x20, 0x01 }, -+ { 0x20, 0x01 } -+ }; -+ u8 r_bp, r_cp; -+ -+ pci_read_config_byte(pdev, port + 1, &r_bp); -+ pci_read_config_byte(pdev, port + 2, &r_cp); -+ -+ r_bp &= ~0xF0; -+ r_cp &= ~0x0F; -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ int speed = adev->dma_mode - XFER_UDMA_0; -+ r_bp |= udma_timing[speed][0]; -+ r_cp |= udma_timing[speed][1]; -+ -+ } else { -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ r_bp |= 0x60; -+ r_cp |= (5 - speed); -+ } -+ pci_write_config_byte(pdev, port + 1, r_bp); -+ pci_write_config_byte(pdev, port + 2, r_cp); -+ -+} -+ -+/** -+ * pdc2026x_reset_engine - Reset the DMA engine -+ * @ap: ATA interface -+ * -+ * Reset the 2026x DMA engine. This is not something we want to do, -+ * and we need to figure out how to serialize this across dual channel -+ * devices if it is neccessary. -+ * -+ * FIXME: Do we need to reset the other interface too ? -+ */ -+ -+static void pdc2026x_reset_engine(struct ata_port *ap) -+{ -+ unsigned long ctrl = ap->host_set->ports[0]->ioaddr.bmdma_addr + 0x1F; -+ -+ u8 val = inb(ctrl); -+ outb(val | 0x10, ctrl); -+ mdelay(100); -+ outb(val & ~0x10, ctrl); -+ mdelay(2000); /* Check - seems to be overkill, plus if needed -+ redo locking */ -+ /* Need to fix up speed info at this point */ -+} -+ -+/** -+ * pdc2026x_bmdma_start - DMA engine begin -+ * @qc: ATA command -+ * -+ * In UDMA3 or higher we have to clock switch for the duration of the -+ * DMA transfer sequence. -+ */ -+ -+static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ int sel66 = ap->hard_port_no ? 0x08: 0x02; -+ /* The clock bits are in the same register for both channels */ -+ unsigned long clock = ap->host_set->ports[0]->ioaddr.bmdma_addr + 0x11; -+ -+ /* Check we keep host_set level locking here */ -+ if (adev->dma_mode >= XFER_UDMA_2) -+ outb(inb(clock) | sel66, clock); -+ else -+ outb(inb(clock) & ~sel66, clock); -+ /* The DMA clocks may have been trashed by a reset. FIXME: make conditional -+ and move to qc_issue ? */ -+ pdc_set_dmamode(ap, qc->dev); -+ /* Activate DMA */ -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * pdc2026x_bmdma_end - DMA engine stop -+ * @qc: ATA command -+ * -+ * After a DMA completes we need to put the clock back to 33MHz for -+ * PIO timings. -+ */ -+ -+static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ int sel66 = ap->hard_port_no ? 0x08: 0x02; -+ /* The clock bits are in the same register for both channels */ -+ unsigned long clock = ap->host_set->ports[0]->ioaddr.bmdma_addr + 0x11; -+ -+ /* FIXME: Review LBA48 code in ide/pci driver */ -+ ata_bmdma_stop(qc); -+ /* Check we keep host_set level locking here */ -+ /* Flip back to 33Mhz for PIO */ -+ if (adev->dma_mode >= XFER_UDMA_2) -+ outb(inb(clock) & ~sel66, clock); -+} -+ -+/** -+ * pdc2026x_eng_timeout - command timeout -+ * @qc: command that timed out -+ * -+ * When the PDC2026x times out hit the controller over the head -+ * with a hammer before continuing. The reset unfortunately also -+ * resets the timing registers so we must reprogram these. -+ */ -+ -+static void pdc2026x_eng_timeout(struct ata_port *ap) -+{ -+ int i; -+ -+ /* Perform libata side housekeeping */ -+ ata_eng_timeout(ap); -+ -+ /* Reset the controller */ -+ pdc2026x_reset_engine(ap); -+ -+ /* Reprogram the device timings */ -+ for (i = 0; i < 2; i++) { -+ struct ata_device *adev = &ap->device[i]; -+ if (ata_dev_present(adev)) { -+ pdc_set_piomode(ap, adev); -+ if (adev->dma_mode) -+ pdc_set_dmamode(ap, adev); -+ } -+ } -+} -+ -+/** -+ * pdc2026x_dev_config - device setup hook -+ * @ap: ATA port -+ * @adev: newly found device -+ * -+ * Perform chip specific early setup. We need to lock the transfer -+ * sizes to 8bit to avoid making the state engine on the 2026x cards -+ * barf. -+ */ -+ -+static void pdc2026x_dev_config(struct ata_port *ap, struct ata_device *adev) -+{ -+ /* We cannot blindly set 256 as the core code may already -+ have picked a lower limit */ -+ -+ if(ap->host->max_sectors > 256) { -+ ap->host->max_sectors = 256; -+ ap->host->hostt->max_sectors = 256; -+ } -+ adev->flags |= ATA_DFLAG_LOCK_SECTORS; -+} -+ -+static struct scsi_host_template pdc_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations pdc2024x_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = pdc_set_piomode, -+ .set_dmamode = pdc_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = pdc2024x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations pdc2026x_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = pdc_set_piomode, -+ .set_dmamode = pdc_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ .dev_config = pdc2026x_dev_config, -+ -+ .phy_reset = pdc2026x_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = pdc2026x_bmdma_start, -+ .bmdma_stop = pdc2026x_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = pdc2026x_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int pdc_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info[3] = { -+ { -+ .sht = &pdc_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA2, -+ .port_ops = &pdc2024x_port_ops -+ }, -+ { -+ .sht = &pdc_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA4, -+ .port_ops = &pdc2026x_port_ops -+ }, -+ { -+ .sht = &pdc_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &pdc2026x_port_ops -+ } -+ -+ }; -+ static struct ata_port_info *port_info[2]; -+ -+ port_info[0] = port_info[1] = &info[id->driver_data]; -+ -+ if (dev->device == PCI_DEVICE_ID_PROMISE_20265) { -+ struct pci_dev *bridge = dev->bus->self; -+ /* Don't grab anything behind a Promise I2O RAID */ -+ if (bridge && bridge->vendor == PCI_VENDOR_ID_INTEL) { -+ if( bridge->device == PCI_DEVICE_ID_INTEL_I960) -+ return -ENODEV; -+ if( bridge->device == PCI_DEVICE_ID_INTEL_I960RM) -+ return -ENODEV; -+ } -+ } -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id pdc[] = { -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { 0, }, -+}; -+ -+static struct pci_driver pdc_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pdc, -+ .probe = pdc_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init pdc_init(void) -+{ -+ return pci_register_driver(&pdc_pci_driver); -+} -+ -+ -+static void __exit pdc_exit(void) -+{ -+ pci_unregister_driver(&pdc_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Promise 2024x and 20262-20267"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, pdc); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(pdc_init); -+module_exit(pdc_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_qdi.c linux-2.6.16-rc6/drivers/scsi/pata_qdi.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_qdi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_qdi.c 2006-02-15 15:08:22.000000000 +0000 -@@ -0,0 +1,370 @@ -+/* -+ * pata_qdi.c - QDI VLB ATA controllers -+ * (C) 2006 Red Hat <alan@redhat.com> -+ * -+ * This driver mostly exists as a proof of concept for non PCI devices under libata. -+ * While the QDI6580 was 'neat' in 1993 it is no longer terribly useful. -+ * -+ * Tuning code written from the documentation at -+ * http://www.ryston.cz/petr/vlb/qd6500.html -+ * http://www.ryston.cz/petr/vlb/qd6580.html -+ * -+ * Probe code based on drivers/ide/legacy/qd65xx.c -+ * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by -+ * Samuel Thibault <samuel.thibault@fnac.net> -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_qdi" -+#define DRV_VERSION "0.2" -+ -+#define NR_HOST 4 /* Two 6580s */ -+ -+struct qdi_data { -+ unsigned long timing; -+ u8 clock[2]; -+ u8 last; -+ int fast; -+ -+}; -+ -+static struct ata_host_set *qdi_host[NR_HOST]; -+static struct qdi_data qdi_data[NR_HOST]; -+static int nr_qdi_host = 0; -+ -+static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct ata_timing t; -+ struct qdi_data *qdi = ap->host_set->private_data; -+ int active, recovery; -+ u8 timing; -+ -+ /* Get the timing data in cycles */ -+ ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); -+ -+ if (qdi->fast) { -+ active = 8 - FIT(t.active, 1, 8); -+ recovery = 18 - FIT(t.recover, 3, 18); -+ } else { -+ active = 9 - FIT(t.active, 2, 9); -+ recovery = 15 - FIT(t.recover, 0, 15); -+ } -+ timing = (recovery << 4) | active | 0x08; -+ -+ qdi->clock[adev->devno] = timing; -+ -+ outb(timing, qdi->timing); -+} -+ -+static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct ata_timing t; -+ struct qdi_data *qdi = ap->host_set->private_data; -+ int active, recovery; -+ u8 timing; -+ -+ /* Get the timing data in cycles */ -+ ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); -+ -+ if (qdi->fast) { -+ active = 8 - FIT(t.active, 1, 8); -+ recovery = 18 - FIT(t.recover, 3, 18); -+ } else { -+ active = 9 - FIT(t.active, 2, 9); -+ recovery = 15 - FIT(t.recover, 0, 15); -+ } -+ timing = (recovery << 4) | active | 0x08; -+ -+ qdi->clock[adev->devno] = timing; -+ -+ outb(timing, qdi->timing); -+ -+ /* Clear the FIFO */ -+ if (adev->class != ATA_DEV_ATA) -+ outb(0x5F, (qdi->timing & 0xFFF0) + 3); -+} -+ -+/** -+ * qdi_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings. -+ */ -+ -+static int qdi_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ struct qdi_data *qdi = ap->host_set->private_data; -+ -+ if (qdi->clock[adev->devno] != qdi->last) { -+ if (adev->pio_mode) { -+ qdi->last = qdi->clock[adev->devno]; -+ outb(qdi->clock[adev->devno], qdi->timing); -+ } -+ } -+ return ata_qc_issue_prot(qc); -+} -+ -+static void qdi_data_xfer(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) -+{ -+ int slop = buflen & 3; -+ -+ if (ata_id_has_dword_io(adev->id)) { -+ if (write_data) -+ outsl(ap->ioaddr.data_addr, buf, buflen >> 2); -+ else -+ insl(ap->ioaddr.data_addr, buf, buflen >> 2); -+ -+ if (unlikely(slop)) { -+ u32 pad; -+ if (write_data) { -+ memcpy(&pad, buf + buflen - slop, slop); -+ outl(le32_to_cpu(pad), ap->ioaddr.data_addr); -+ } else { -+ pad = cpu_to_le16(inl(ap->ioaddr.data_addr)); -+ memcpy(buf + buflen - slop, &pad, slop); -+ } -+ } -+ } else -+ ata_pio_data_xfer(ap, adev, buf, buflen, write_data); -+} -+ -+static struct scsi_host_template qdi_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations qdi6500_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = qdi6500_set_piomode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = qdi_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = qdi_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations qdi6580_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = qdi6580_set_piomode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = qdi_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = qdi_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * qdi_init_one - attach a qdi interface -+ * @type: Type to display -+ * @io: I/O port start -+ * @irq: interrupt line -+ * @fast: True if on a > 33Mhz VLB -+ * -+ * Register an ISA bus IDE interface. Such interfaces are PIO and we -+ * assume do not support IRQ sharing. -+ */ -+ -+static __init int qdi_init_one(unsigned long port, int type, unsigned long io, int irq, int fast) -+{ -+ struct ata_probe_ent ae; -+ int ret; -+ -+ unsigned long ctrl = io + 0x206; -+ -+ /* -+ * Fill in a probe structure first of all -+ */ -+ -+ memset(&ae, 0, sizeof(struct ata_probe_ent)); -+ INIT_LIST_HEAD(&ae.node); -+ ae.dev = NULL; -+ -+ if (type == 6580) { -+ ae.port_ops = &qdi6580_port_ops; -+ ae.pio_mask = 0x1F; -+ } else { -+ ae.port_ops = &qdi6500_port_ops; -+ ae.pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */ -+ } -+ -+ ae.sht = &qdi_sht; -+ ae.n_ports = 1; -+ ae.irq = irq; -+ ae.irq_flags = 0; -+ ae.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IRQ_MASK; -+ ae.port[0].cmd_addr = io; -+ ae.port[0].altstatus_addr = ctrl; -+ ae.port[0].ctl_addr = ctrl; -+ ata_std_ports(&ae.port[0]); -+ -+ /* -+ * Hook in a private data structure per channel -+ */ -+ ae.private_data = &qdi_data[nr_qdi_host]; -+ -+ qdi_data[nr_qdi_host].timing = port; -+ qdi_data[nr_qdi_host].fast = fast; -+ -+ printk(KERN_INFO DRV_NAME": qd%d at 0x%lx.\n", type, io); -+ ret = ata_device_add(&ae); -+ if (ret == 0) -+ return -ENODEV; -+ -+ qdi_host[nr_qdi_host++] = ae.host_set; -+ return 0; -+} -+ -+/** -+ * qdi_init - attach qdi interfaces -+ * -+ * Attach qdi IDE interfaces by scanning the ports it may occupy. -+ */ -+ -+static __init int qdi_init(void) -+{ -+ unsigned long flags; -+ unsigned long qd_port[2] = { 0x30, 0xB0 }; -+ unsigned long ide_port[2] = { 0x170, 0x1F0 }; -+ int ide_irq[2] = { 14, 15 }; -+ int ct = 0; -+ int i; -+ -+ /* -+ * Check each possible QD65xx base address -+ */ -+ -+ for (i = 0; i < 2; i++) { -+ unsigned long port = qd_port[i]; -+ u8 r, res; -+ -+ -+ if (request_region(port, 2, "pata_qdi")) { -+ /* Check for a card */ -+ local_irq_save(flags); -+ r = inb_p(port); -+ outb_p(0x19, port); -+ res = inb_p(port); -+ outb_p(r, port); -+ local_irq_restore(flags); -+ -+ /* Fail */ -+ if (res == 0x19) -+ { -+ release_region(port, 2); -+ continue; -+ } -+ -+ /* Passes the presence test */ -+ r = inb_p(port + 1); /* Check port agrees with port set */ -+ if ((r & 2) >> 1 != i) { -+ release_region(port, 2); -+ continue; -+ } -+ -+ /* Check card type */ -+ if ((r & 0xF0) == 0xC0) { -+ /* QD6500: single channel */ -+ if (r & 8) { -+ /* Disabled ? */ -+ release_region(port, 2); -+ continue; -+ } -+ ct += qdi_init_one(port, 6500, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); -+ } -+ if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) { -+ /* QD6580: dual channel */ -+ if (!request_region(port + 2 , 2, "pata_qdi")) -+ { -+ release_region(port, 2); -+ continue; -+ } -+ res = inb(port + 3); -+ if (res & 1) { -+ /* Single channel mode */ -+ ct += qdi_init_one(port, 6580, ide_port[r & 0x01], ide_irq[r & 0x01], r & 0x04); -+ } else { -+ /* Dual channel mode */ -+ ct += qdi_init_one(port, 6580, 0x1F0, 14, r & 0x04); -+ ct += qdi_init_one(port + 2, 6580, 0x170, 15, r & 0x04); -+ } -+ } -+ } -+ } -+ if (ct != 0) -+ return 0; -+ return -ENODEV; -+} -+ -+static __exit void qdi_exit(void) -+{ -+ int i; -+ -+ for (i = 0; i < nr_qdi_host; i++) { -+ ata_host_set_remove(qdi_host[i]); -+ /* Free the control resource. The 6580 dual channel has the resources -+ * claimed as a pair of 2 byte resources so we need no special cases... -+ */ -+ release_region(qdi_data[i].timing, 2); -+ } -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for qdi ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(qdi_init); -+module_exit(qdi_exit); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_radisys.c linux-2.6.16-rc6/drivers/scsi/pata_radisys.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_radisys.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_radisys.c 2006-02-17 15:31:12.000000000 +0000 -@@ -0,0 +1,321 @@ -+/* -+ * pata_radisys.c - Intel PATA/SATA controllers -+ * -+ * (C) 2006 Red Hat <alan@redhat.com> -+ * -+ * Some parts based on ata_piix.c by Jeff Garzik and others. -+ * -+ * A PIIX relative, this device has a single ATA channel and no -+ * slave timings, SITRE or PPE. In that sense it is a close relative -+ * of the original PIIX. It does however support UDMA 33/66 per channel -+ * although no other modes/timings. Also lacking is 32bit I/O on the ATA -+ * port. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_radisys" -+#define DRV_VERSION "0.2" -+ -+/** -+ * radisys_pata_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void radisys_pata_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA80; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * radisys_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set PIO mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void radisys_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ unsigned int pio = adev->pio_mode - XFER_PIO_0; -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ u16 idetm_data; -+ int control = 0; -+ -+ /* -+ * See Intel Document 298600-004 for the timing programing rules -+ * for PIIX/ICH. Note that the early PIIX does not have the slave -+ * timing port at 0x44. The Radisys is a relative of the PIIX -+ * but not the same so be careful. -+ */ -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, /* Check me */ -+ { 0, 0 }, -+ { 1, 1 }, -+ { 2, 2 }, -+ { 3, 3 }, }; -+ -+ if (pio > 0) -+ control |= 1; /* TIME1 enable */ -+ if (ata_pio_need_iordy(adev)) -+ control |= 2; /* IE IORDY */ -+ -+ pci_read_config_word(dev, 0x40, &idetm_data); -+ -+ /* Enable IE and TIME as appropriate. Clear the other -+ drive timing bits */ -+ idetm_data &= 0xCCCC; -+ idetm_data |= (control << (4 * adev->devno)); -+ idetm_data |= (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ pci_write_config_word(dev, 0x40, idetm_data); -+ -+ /* Track which port is configured */ -+ ap->private_data = adev; -+} -+ -+/** -+ * radisys_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * @isich: True if the device is an ICH and has IOCFG registers -+ * -+ * Set MWDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void radisys_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -+ u16 idetm_data; -+ u8 udma_enable; -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 1 }, -+ { 2, 2 }, -+ { 3, 3 }, }; -+ -+ /* -+ * MWDMA is driven by the PIO timings. We must also enable -+ * IORDY unconditionally. -+ */ -+ -+ pci_read_config_word(dev, 0x40, &idetm_data); -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; -+ const unsigned int needed_pio[3] = { -+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 -+ }; -+ int pio = needed_pio[mwdma] - XFER_PIO_0; -+ int control = 3; /* IORDY|TIME0 */ -+ -+ /* If the drive MWDMA is faster than it can do PIO then -+ we must force PIO0 for PIO cycles. */ -+ -+ if (adev->pio_mode < needed_pio[mwdma]) -+ control = 1; -+ -+ /* Mask out the relevant control and timing bits we will load. Also -+ clear the other drive TIME register as a precaution */ -+ -+ idetm_data &= 0xCCCC; -+ idetm_data |= control << (4 * adev->devno); -+ idetm_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); -+ -+ udma_enable &= ~(1 << adev->devno); -+ } else { -+ u8 udma_mode; -+ -+ /* UDMA66 on. It isn't clear from the documentation whether -+ UDMA 33 and 66 are switchable via register 0x4A */ -+ -+ pci_read_config_byte(dev, 0x4A, &udma_mode); -+ -+ if (adev->xfer_mode == XFER_UDMA_2) -+ udma_mode &= ~ (1 << adev->devno); -+ else /* UDMA 4 */ -+ udma_mode |= (1 << adev->devno); -+ -+ pci_write_config_byte(dev, 0x4A, udma_mode); -+ -+ udma_enable |= (1 << adev->devno); -+ } -+ pci_write_config_word(dev, 0x40, idetm_data); -+ pci_write_config_byte(dev, 0x48, udma_enable); -+ -+ /* Track which port is configured */ -+ ap->private_data = adev; -+} -+ -+/** -+ * radisys_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Our logic also clears TIME0/TIME1 for the other device so -+ * that, even if we get this wrong, cycles to the other device will -+ * be made PIO0. -+ */ -+ -+static int radisys_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ -+ if (adev != ap->private_data) { -+ /* UDMA timing is not shared */ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ if (adev->dma_mode) -+ radisys_set_dmamode(ap, adev); -+ else if (adev->pio_mode) -+ radisys_set_piomode(ap, adev); -+ } -+ } -+ return ata_qc_issue_prot(qc); -+} -+ -+ -+static struct scsi_host_template radisys_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations radisys_pata_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = radisys_set_piomode, -+ .set_dmamode = radisys_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = radisys_pata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = radisys_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+ -+/** -+ * radisys_init_one - Register PIIX ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in radisys_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. We probe for combined mode (sigh), -+ * and then hand over control to libata, for it to do the rest. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ static struct ata_port_info info = { -+ .sht = &radisys_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma1-2 */ -+ .udma_mask = 0x14, /* UDMA33/66 only */ -+ .port_ops = &radisys_pata_ops, -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id radisys_pci_tbl[] = { -+ { 0x1331, 0x8201, PCI_ANY_ID, PCI_ANY_ID, }, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver radisys_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = radisys_pci_tbl, -+ .probe = radisys_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init radisys_init(void) -+{ -+ return pci_register_driver(&radisys_pci_driver); -+} -+ -+static void __exit radisys_exit(void) -+{ -+ pci_unregister_driver(&radisys_pci_driver); -+} -+ -+ -+module_init(radisys_init); -+module_exit(radisys_exit); -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("SCSI low-level driver for Radisys R82600 controllers"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, radisys_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_rz1000.c linux-2.6.16-rc6/drivers/scsi/pata_rz1000.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_rz1000.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_rz1000.c 2006-02-16 15:38:18.000000000 +0000 -@@ -0,0 +1,183 @@ -+/* -+ * RZ1000/1001 driver based upon -+ * -+ * linux/drivers/ide/pci/rz1000.c Version 0.06 January 12, 2003 -+ * Copyright (C) 1995-1998 Linus Torvalds & author (see below) -+ * Principal Author: mlord@pobox.com (Mark Lord) -+ * -+ * See linux/MAINTAINERS for address of current maintainer. -+ * -+ * This file provides support for disabling the buggy read-ahead -+ * mode of the RZ1000 IDE chipset, commonly used on Intel motherboards. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "rz1000" -+#define DRV_VERSION "0.01" -+ -+static void rz1000_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * rz1000_set_mode - mode setting function -+ * @ap: ATA interface -+ * -+ * Use a non standard set_mode function. We don't want to be tuned. We -+ * would prefer to be BIOS generic but for the fact our hardware is -+ * whacked out. -+ */ -+ -+static void rz1000_set_mode(struct ata_port *ap) -+{ -+ int i; -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ /* We don't really care */ -+ dev->pio_mode = XFER_PIO_0; -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+} -+ -+ -+static struct scsi_host_template rz1000_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations rz1000_port_ops = { -+ .set_mode = rz1000_set_mode, -+ -+ .port_disable = ata_port_disable, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = rz1000_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * rz1000_init_one - Register RZ1000 ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in rz1000_pci_tbl matching with @pdev -+ * -+ * Configure an RZ1000 interface. This doesn't require much special -+ * handling except that we *MUST* kill the chipset readahead or the -+ * user may experience data corruption. -+ */ -+ -+static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ struct ata_port_info *port_info[2]; -+ u16 reg; -+ static struct ata_port_info info = { -+ .sht = &rz1000_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .port_ops = &rz1000_port_ops -+ }; -+ -+ if (!printed_version++) -+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); -+ -+ /* Be exceptionally paranoid as we must be sure to apply the fix */ -+ if (pci_read_config_word(pdev, 0x40, ®) != 0) -+ goto fail; -+ reg &= 0xDFFF; -+ if (pci_write_config_word(pdev, 0x40, reg) != 0) -+ goto fail; -+ printk(KERN_INFO DRV_NAME ": disabled chipset readahead.\n"); -+ -+ port_info[0] = &info; -+ port_info[1] = &info; -+ return ata_pci_init_one(pdev, port_info, 2); -+fail: -+ printk(KERN_ERR DRV_NAME ": failed to disable read-ahead on chipset..\n"); -+ /* Not safe to use so skip */ -+ return -ENODEV; -+} -+ -+static struct pci_device_id pata_rz1000[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001), }, -+ { 0, }, -+}; -+ -+static struct pci_driver rz1000_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pata_rz1000, -+ .probe = rz1000_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+ -+static int __init rz1000_init(void) -+{ -+ return pci_register_driver(&rz1000_pci_driver); -+} -+ -+static void __exit rz1000_exit(void) -+{ -+ pci_unregister_driver(&rz1000_pci_driver); -+} -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for RZ1000 PCI ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, pata_rz1000); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(rz1000_init); -+module_exit(rz1000_exit); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sc1200.c linux-2.6.16-rc6/drivers/scsi/pata_sc1200.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sc1200.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_sc1200.c 2006-03-10 17:07:03.000000000 +0000 -@@ -0,0 +1,286 @@ -+/* -+ * New ATA layer SC1200 driver Alan Cox <alan@redhat.com> -+ * -+ * TODO: Mode selection filtering -+ * TODO: Can't enable second channel until ATA core has serialize -+ * TODO: Needs custom DMA cleanup code -+ * -+ * Based very heavily on -+ * -+ * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 -+ * -+ * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> -+ * May be copied or modified under the terms of the GNU General Public License -+ * -+ * Development of this chipset driver was funded -+ * by the nice folks at National Semiconductor. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "sc1200" -+#define DRV_VERSION "0.2" -+ -+#define SC1200_REV_A 0x00 -+#define SC1200_REV_B1 0x01 -+#define SC1200_REV_B3 0x02 -+#define SC1200_REV_C1 0x03 -+#define SC1200_REV_D1 0x04 -+ -+/** -+ * sc1200_clock - PCI clock -+ * -+ * Return the PCI bus clocking for the SC1200 chipset configuration -+ * in use. We return 0 for 33MHz 1 for 48MHz and 2 for 66Mhz -+ */ -+ -+static int sc1200_clock(void) -+{ -+ /* Magic registers that give us the chipset data */ -+ u8 chip_id = inb(0x903C); -+ u8 silicon_rev = inb(0x903D); -+ u16 pci_clock; -+ -+ if (chip_id == 0x04 && silicon_rev < SC1200_REV_B1) -+ return 0; /* 33 MHz mode */ -+ -+ /* Clock generator configuration 0x901E its 8/9 are the PCI clocking -+ 0/3 is 33Mhz 1 is 48 2 is 66 */ -+ -+ pci_clock = inw(0x901E); -+ pci_clock >>= 8; -+ pci_clock &= 0x03; -+ if (pci_clock == 3) -+ pci_clock = 0; -+ return pci_clock; -+} -+ -+/** -+ * sc1200_set_piomode - PIO setup -+ * @ap: ATA interface -+ * @adev: device on the interface -+ * -+ * Set our PIO requirements. This is fairly simple on the SC1200 -+ */ -+ -+static void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u32 pio_timings[4][5] = { -+ {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz -+ {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz -+ {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz -+ {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131} // format1, 66Mhz -+ }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 format; -+ unsigned int reg = 0x40 + 0x10 * ap->hard_port_no; -+ int mode = adev->pio_mode - XFER_PIO_0; -+ -+ pci_read_config_dword(pdev, reg + 4, &format); -+ format >>= 31; -+ format += sc1200_clock(); -+ pci_write_config_dword(pdev, reg + 8 * adev->devno, -+ pio_timings[format][mode]); -+} -+ -+/** -+ * sc1200_set_dmamode - DMA timing setup -+ * @ap: ATA interface -+ * @adev: Device being configured -+ * -+ * We cannot mix MWDMA and UDMA without reloading timings each switch -+ * master to slave. -+ */ -+ -+static void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u32 udma_timing[3][3] = { -+ { 0x00921250, 0x00911140, 0x00911030 }, -+ { 0x00932470, 0x00922260, 0x00922140 }, -+ { 0x009436A1, 0x00933481, 0x00923261 } -+ }; -+ -+ static u32 mwdma_timing[3][3] = { -+ { 0x00077771, 0x00012121, 0x00002020 }, -+ { 0x000BBBB2, 0x00024241, 0x00013131 }, -+ { 0x000FFFF3, 0x00035352, 0x00015151 } -+ }; -+ -+ int clock = sc1200_clock(); -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ unsigned int reg = 0x40 + 0x10 * ap->hard_port_no; -+ int mode = adev->dma_mode; -+ u32 format; -+ -+ if (mode >= XFER_UDMA_0) -+ format = udma_timing[clock][mode - XFER_UDMA_0]; -+ else -+ format = mwdma_timing[clock][mode - XFER_MW_DMA_0]; -+ -+ if (adev->devno == 0) { -+ u32 timings; -+ -+ pci_read_config_dword(pdev, reg + 4, &timings); -+ timings &= 0x80000000UL; -+ timings |= format; -+ pci_write_config_dword(pdev, reg + 4, timings); -+ } else -+ pci_write_config_dword(pdev, reg + 12, format); -+} -+ -+/** -+ * sc1200_qc_issue_prot - command issue -+ * @qc: command pending -+ * -+ * Called when the libata layer is about to issue a command. We wrap -+ * this interface so that we can load the correct ATA timings if -+ * neccessary. Specifically we have a problem that there is only -+ * one MWDMA/UDMA bit. -+ */ -+ -+static int sc1200_qc_issue_prot(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ struct ata_device *adev = qc->dev; -+ struct ata_device *prev = ap->private_data; -+ -+ /* See if the DMA settings could be wrong */ -+ if (adev->dma_mode != 0 && adev != prev && prev != NULL) { -+ /* Maybe, but do the channels match MWDMA/UDMA ? */ -+ if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || -+ (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) -+ /* Switch the mode bits */ -+ sc1200_set_dmamode(ap, adev); -+ } -+ -+ return ata_qc_issue_prot(qc); -+} -+ -+static struct scsi_host_template sc1200_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations sc1200_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sc1200_set_piomode, -+ .set_dmamode = sc1200_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = sc1200_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * sc1200_init_one - Initialise an SC1200 -+ * @dev: PCI device -+ * @id: Entry in match table -+ * -+ * Just throw the needed data at the libata helper and it does all -+ * our work. -+ */ -+ -+static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &sc1200_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x07, -+ .port_ops = &sc1200_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ /* Can't enable port 2 yet, see top comments */ -+ return ata_pci_init_one(dev, port_info, 1); -+} -+ -+static struct pci_device_id sc1200[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE), }, -+ { 0, }, -+}; -+ -+static struct pci_driver sc1200_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = sc1200, -+ .probe = sc1200_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init sc1200_init(void) -+{ -+ return pci_register_driver(&sc1200_pci_driver); -+} -+ -+ -+static void __exit sc1200_exit(void) -+{ -+ pci_unregister_driver(&sc1200_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox, Mark Lord"); -+MODULE_DESCRIPTION("low-level driver for the NS/AMD SC1200"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, sc1200); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(sc1200_init); -+module_exit(sc1200_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_serverworks.c linux-2.6.16-rc6/drivers/scsi/pata_serverworks.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_serverworks.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_serverworks.c 2006-02-16 15:37:31.000000000 +0000 -@@ -0,0 +1,586 @@ -+/* -+ * ata-serverworks.c - Serverworks PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon -+ * -+ * serverworks.c -+ * -+ * Copyright (C) 1998-2000 Michel Aubry -+ * Copyright (C) 1998-2000 Andrzej Krzysztofowicz -+ * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> -+ * Portions copyright (c) 2001 Sun Microsystems -+ * -+ * -+ * RCC/ServerWorks IDE driver for Linux -+ * -+ * OSB4: `Open South Bridge' IDE Interface (fn 1) -+ * supports UDMA mode 2 (33 MB/s) -+ * -+ * CSB5: `Champion South Bridge' IDE Interface (fn 1) -+ * all revisions support UDMA mode 4 (66 MB/s) -+ * revision A2.0 and up support UDMA mode 5 (100 MB/s) -+ * -+ * *** The CSB5 does not provide ANY register *** -+ * *** to detect 80-conductor cable presence. *** -+ * -+ * CSB6: `Champion South Bridge' IDE Interface (optional: third channel) -+ * -+ * Documentation: -+ * Available under NDA only. Errata info very hard to get. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "serverworks" -+#define DRV_VERSION "0.1.1" -+ -+#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ -+#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ -+ -+/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 -+ * can overrun their FIFOs when used with the CSB5 */ -+ -+static const char *csb_bad_ata100[] = { -+ "ST320011A", -+ "ST340016A", -+ "ST360021A", -+ "ST380021A", -+ NULL -+}; -+ -+/** -+ * dell_cable - Dell serverworks cable detection -+ * @ap: ATA port to do cable detect -+ * -+ * Dell hide the 40/80 pin select for their interfaces in the top two -+ * bits of the subsystem ID. -+ */ -+ -+static int dell_cable(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ if (pdev->subsystem_device & (1 << (ap->hard_port_no + 14))) -+ return ATA_CBL_PATA80; -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * sun_cable - Sun Cobalt 'Alpine' cable detection -+ * @ap: ATA port to do cable select -+ * -+ * Cobalt CSB5 IDE hides the 40/80pin in the top two bits of the -+ * subsystem ID the same as dell. We could use one function but we may -+ * need to extend the Dell one in future -+ */ -+ -+static int sun_cable(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ if (pdev->subsystem_device & (1 << (ap->hard_port_no + 14))) -+ return ATA_CBL_PATA80; -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * osb4_cable - OSB4 cable detect -+ * @ap: ATA port to check -+ * -+ * The OSB4 isn't UDMA66 capable so this is easy -+ */ -+ -+static int osb4_cable(struct ata_port *ap) { -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * csb4_cable - CSB5/6 cable detect -+ * @ap: ATA port to check -+ * -+ * Serverworks default arrangement is to use the drive side detection -+ * only. -+ */ -+ -+static int csb_cable(struct ata_port *ap) { -+ return ATA_CBL_PATA80; -+} -+ -+struct sv_cable_table { -+ int device; -+ int subvendor; -+ int (*cable_detect)(struct ata_port *ap); -+}; -+ -+/* -+ * Note that we don't copy the old serverworks code because the old -+ * code contains obvious mistakes -+ */ -+ -+static struct sv_cable_table cable_detect[] = { -+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_DELL, dell_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_VENDOR_ID_DELL, dell_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_VENDOR_ID_SUN, sun_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_OSB4, PCI_ANY_ID, osb4_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, csb_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, csb_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, csb_cable }, -+ { PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, csb_cable }, -+ { } -+}; -+ -+/** -+ * serverworks_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection according to the device and subvendor -+ * identifications -+ */ -+ -+static int serverworks_cable_detect(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct sv_cable_table *cb = cable_detect; -+ -+ while(cb->device) { -+ if (cb->device == pdev->device && -+ (cb->subvendor == pdev->subsystem_vendor || -+ cb->subvendor == PCI_ANY_ID)) { -+ return cb->cable_detect(ap); -+ } -+ cb++; -+ } -+ BUG(); -+} -+ -+static void serverworks_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = serverworks_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * serverworks_is_csb - Check for CSB or OSB -+ * @pdev: PCI device to check -+ * -+ * Returns true if the device being checked is known to be a CSB -+ * series device. -+ */ -+ -+static u8 serverworks_is_csb(struct pci_dev *pdev) -+{ -+ switch (pdev->device) { -+ case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: -+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: -+ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: -+ case PCI_DEVICE_ID_SERVERWORKS_HT1000IDE: -+ return 1; -+ default: -+ break; -+ } -+ return 0; -+} -+ -+/** -+ * serverworks_osb4_filter - mode selection filter -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Filter the offered modes for the device to apply controller -+ * specific rules. OSB4 requires no UDMA for disks due to a FIFO -+ * bug we hit. -+ */ -+ -+static unsigned int serverworks_osb4_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ if (adev->class == ATA_DEV_ATA) -+ return 0; -+ return mask; -+} -+ -+ -+/** -+ * serverworks_csb_filter - mode selection filter -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Check the blacklist and disable UDMA5 if matched -+ */ -+ -+static unsigned int serverworks_csb_filter(const struct ata_port *ap, struct ata_device *adev, unsigned int mask, int shift) -+{ -+ const char *p; -+ char model_num[40]; -+ int len, i; -+ -+ /* Disk, UDMA */ -+ if (shift != ATA_SHIFT_UDMA) -+ return mask; -+ if (adev->class != ATA_DEV_ATA) -+ return mask; -+ -+ /* Actually do need to check */ -+ ata_dev_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); -+ /* Precuationary - why not do this in the libata core ?? */ -+ -+ len = strlen(model_num); -+ while ((len > 0) && (model_num[len - 1] == ' ')) { -+ len--; -+ model_num[len] = 0; -+ } -+ -+ for(i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { -+ if (!strncmp(p, model_num, len)) -+ return mask & 0x1F; -+ } -+ return mask; -+} -+ -+ -+/** -+ * serverworks_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the OSB4/CSB5 timing registers for PIO. The PIO register -+ * load is done as a simple lookup. -+ */ -+static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; -+ int offset = 1 + 2 * ap->hard_port_no - adev->devno; -+ int devbits = (2 * ap->hard_port_no + adev->devno) * 4; -+ u16 csb5_pio; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int pio = adev->pio_mode - XFER_PIO_0; -+ -+ pci_write_config_byte(pdev, 0x40 + offset, pio_mode[pio]); -+ -+ /* The OSB4 just requires the timing but the CSB series want the -+ mode number as well */ -+ if (serverworks_is_csb(pdev)) { -+ pci_read_config_word(pdev, 0x4A, &csb5_pio); -+ csb5_pio &= ~(0x0F << devbits); -+ pci_write_config_byte(pdev, 0x4A, csb5_pio | (pio << devbits)); -+ } -+} -+ -+/** -+ * serverworks_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the MWDMA/UDMA modes for the serverworks OSB4/CSB5 -+ * chipset. The MWDMA mode values are pulled from a lookup table -+ * while the chipset uses mode number for UDMA. -+ */ -+ -+static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u8 dma_mode[] = { 0x77, 0x21, 0x20 }; -+ int offset = 1 + 2 * ap->hard_port_no - adev->devno; -+ int devbits = (2 * ap->hard_port_no + adev->devno); -+ u8 ultra; -+ u8 ultra_cfg; -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ -+ pci_read_config_byte(pdev, 0x54, &ultra_cfg); -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ pci_write_config_byte(pdev, 0x44 + offset, 0x20); -+ -+ pci_read_config_byte(pdev, 0x56 + ap->hard_port_no, &ultra); -+ ultra &= ~(0x0F << (ap->hard_port_no * 4)); -+ ultra |= (adev->dma_mode - XFER_UDMA_0) -+ << (ap->hard_port_no * 4); -+ pci_write_config_byte(pdev, 0x56 + ap->hard_port_no, ultra); -+ -+ ultra_cfg |= (1 << devbits); -+ } else { -+ pci_write_config_byte(pdev, 0x44 + offset, -+ dma_mode[adev->dma_mode - XFER_MW_DMA_0]); -+ ultra_cfg &= ~(1 << devbits); -+ } -+ pci_write_config_byte(pdev, 0x54, ultra_cfg); -+} -+ -+static struct scsi_host_template serverworks_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations serverworks_osb4_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = serverworks_set_piomode, -+ .set_dmamode = serverworks_set_dmamode, -+ .mode_filter = serverworks_osb4_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = serverworks_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations serverworks_csb_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = serverworks_set_piomode, -+ .set_dmamode = serverworks_set_dmamode, -+ .mode_filter = serverworks_csb_filter, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = serverworks_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int serverworks_fixup_osb4(struct pci_dev *pdev) -+{ -+ u32 reg; -+ struct pci_dev *isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, -+ PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); -+ if (isa_dev) { -+ pci_read_config_dword(isa_dev, 0x64, ®); -+ reg &= ~0x00002000; /* disable 600ns interrupt mask */ -+ if (!(reg & 0x00004000)) -+ printk(KERN_DEBUG DRV_NAME ": UDMA not BIOS enabled.\n"); -+ reg |= 0x00004000; /* enable UDMA/33 support */ -+ pci_write_config_dword(isa_dev, 0x64, reg); -+ pci_dev_put(isa_dev); -+ return 0; -+ } -+ printk(KERN_WARNING "ata_serverworks: Unable to find bridge.\n"); -+ return -ENODEV; -+} -+ -+static int serverworks_fixup_csb(struct pci_dev *pdev) -+{ -+ u8 rev; -+ u8 btr; -+ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); -+ -+ /* Third Channel Test */ -+ if (!(PCI_FUNC(pdev->devfn) & 1)) { -+ struct pci_dev * findev = NULL; -+ u32 reg4c = 0; -+ findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, -+ PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); -+ if (findev) { -+ pci_read_config_dword(findev, 0x4C, ®4c); -+ reg4c &= ~0x000007FF; -+ reg4c |= 0x00000040; -+ reg4c |= 0x00000020; -+ pci_write_config_dword(findev, 0x4C, reg4c); -+ pci_dev_put(findev); -+ } -+ } else { -+ struct pci_dev * findev = NULL; -+ u8 reg41 = 0; -+ -+ findev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, -+ PCI_DEVICE_ID_SERVERWORKS_CSB6, NULL); -+ if (findev) { -+ pci_read_config_byte(findev, 0x41, ®41); -+ reg41 &= ~0x40; -+ pci_write_config_byte(findev, 0x41, reg41); -+ pci_dev_put(findev); -+ } -+ } -+ /* setup the UDMA Control register -+ * -+ * 1. clear bit 6 to enable DMA -+ * 2. enable DMA modes with bits 0-1 -+ * 00 : legacy -+ * 01 : udma2 -+ * 10 : udma2/udma4 -+ * 11 : udma2/udma4/udma5 -+ */ -+ pci_read_config_byte(pdev, 0x5A, &btr); -+ btr &= ~0x40; -+ if (!(PCI_FUNC(pdev->devfn) & 1)) -+ btr |= 0x2; -+ else -+ btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; -+ pci_write_config_byte(pdev, 0x5A, btr); -+ -+ return btr; -+} -+ -+static void serverworks_fixup_ht1000(struct pci_dev *pdev) -+{ -+ u8 btr; -+ /* Setup HT1000 SouthBridge Controller - Single Channel Only */ -+ pci_read_config_byte(pdev, 0x5A, &btr); -+ btr &= ~0x40; -+ btr |= 0x3; -+ pci_write_config_byte(pdev, 0x5A, btr); -+} -+ -+ -+static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ int ports = 2; -+ static struct ata_port_info info[4] = { -+ { /* OSB4 */ -+ .sht = &serverworks_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x07, -+ .port_ops = &serverworks_osb4_port_ops -+ }, { /* OSB4 no UDMA */ -+ .sht = &serverworks_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x00, -+ .port_ops = &serverworks_osb4_port_ops -+ }, { /* CSB5 */ -+ .sht = &serverworks_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, -+ .port_ops = &serverworks_csb_port_ops -+ }, { /* CSB5 - later revisions*/ -+ .sht = &serverworks_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &serverworks_csb_port_ops -+ } -+ }; -+ static struct ata_port_info *port_info[2]; -+ struct ata_port_info *devinfo = &info[id->driver_data]; -+ -+ /* Force master latency timer to 64 PCI clocks */ -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); -+ -+ /* OSB4 : South Bridge and IDE */ -+ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { -+ /* Select non UDMA capable OSB4 if we can't do fixups */ -+ if ( serverworks_fixup_osb4(pdev) < 0) -+ devinfo = &info[1]; -+ } -+ /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ -+ else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || -+ (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || -+ (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) { -+ -+ /* If the returned btr is the newer revision then -+ select the right info block */ -+ if (serverworks_fixup_csb(pdev) == 3) -+ devinfo = &info[3]; -+ -+ /* Is this the 3rd channel CSB6 IDE ? */ -+ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) -+ ports = 1; -+ } -+ /* setup HT1000E */ -+ else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) -+ serverworks_fixup_ht1000(pdev); -+ -+ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) -+ ata_pci_clear_simplex(pdev); -+ -+ port_info[0] = port_info[1] = devinfo; -+ return ata_pci_init_one(pdev, port_info, ports); -+} -+ -+static struct pci_device_id serverworks[] = { -+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, -+ { 0, }, -+}; -+ -+static struct pci_driver serverworks_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = serverworks, -+ .probe = serverworks_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init serverworks_init(void) -+{ -+ return pci_register_driver(&serverworks_pci_driver); -+} -+ -+ -+static void __exit serverworks_exit(void) -+{ -+ pci_unregister_driver(&serverworks_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Serverworks OSB4/CSB5/CSB6"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, serverworks); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(serverworks_init); -+module_exit(serverworks_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sil680.c linux-2.6.16-rc6/drivers/scsi/pata_sil680.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sil680.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_sil680.c 2006-03-01 16:24:18.000000000 +0000 -@@ -0,0 +1,377 @@ -+/* -+ * pata_sil680.c - SIL680 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon -+ * -+ * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003 -+ * -+ * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> -+ * Copyright (C) 2003 Red Hat <alan@redhat.com> -+ * -+ * May be copied or modified under the terms of the GNU General Public License -+ * -+ * Documentation publically available. -+ * -+ * If you have strange problems with nVidia chipset systems please -+ * see the SI support documentation and update your system BIOS -+ * if neccessary -+ * -+ * TODO -+ * If we know all our devices are LBA28 (or LBA28 sized) we could use -+ * the command fifo mode. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_sil680" -+#define DRV_VERSION "0.2.1" -+ -+/** -+ * sil680_selreg - return register base -+ * @hwif: interface -+ * @r: config offset -+ * -+ * Turn a config register offset into the right address in either -+ * PCI space or MMIO space to access the control register in question -+ * Thankfully this is a configuration operation so isnt performance -+ * criticial. -+ */ -+ -+static unsigned long sil680_selreg(struct ata_port *ap, int r) -+{ -+ unsigned long base = 0xA0 + r; -+ base += (ap->hard_port_no << 4); -+ return base; -+} -+ -+/** -+ * sil680_seldev - return register base -+ * @hwif: interface -+ * @r: config offset -+ * -+ * Turn a config register offset into the right address in either -+ * PCI space or MMIO space to access the control register in question -+ * including accounting for the unit shift. -+ */ -+ -+static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r) -+{ -+ unsigned long base = 0xA0 + r; -+ base += (ap->hard_port_no << 4); -+ base |= adev->devno ? 2 : 0; -+ return base; -+} -+ -+ -+/** -+ * sil680_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection. The SIL680 stores this in PCI config -+ * space for us. -+ */ -+ -+static int sil680_cable_detect(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ unsigned long addr = sil680_selreg(ap, 0); -+ u8 ata66; -+ pci_read_config_byte(pdev, addr, &ata66); -+ if (ata66 & 1) -+ return ATA_CBL_PATA80; -+ else -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * sil680_bus_reset - reset the SIL680 bus -+ * @ap: ATA port to reset -+ * -+ * Perform the SIL680 housekeeping when doing an ATA bus reset -+ */ -+ -+static void sil680_bus_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ unsigned long addr = sil680_selreg(ap, 0); -+ u8 reset; -+ -+ pci_read_config_byte(pdev, addr, &reset); -+ pci_write_config_byte(pdev, addr, reset | 0x03); -+ udelay(25); -+ pci_write_config_byte(pdev, addr, reset); -+ ata_bus_reset(ap); -+} -+ -+static void sil680_phy_reset(struct ata_port *ap) -+{ -+ ap->cbl = sil680_cable_detect(ap); -+ sil680_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * sil680_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the SIL680 registers for PIO mode. Note that the task speed -+ * registers are shared between the devices so we must pick the lowest -+ * mode for command work. -+ */ -+ -+static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u16 speed_p[5] = { 0x328A, 0x2283, 0x1104, 0x10C3, 0x10C1 }; -+ static u16 speed_t[5] = { 0x328A, 0x1281, 0x1281, 0x10C3, 0x10C1 }; -+ -+ unsigned long tfaddr = sil680_selreg(ap, 0x02); -+ unsigned long addr = sil680_seldev(ap, adev, 0x04); -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int pio = adev->pio_mode - XFER_PIO_0; -+ int lowest_pio = pio; -+ u16 reg; -+ -+ struct ata_device *pair = ata_dev_pair(ap, adev); -+ -+ if (pair != NULL) { -+ if (adev->pio_mode > pair->pio_mode) -+ lowest_pio = pair->pio_mode - XFER_PIO_0; -+ } -+ -+ pci_write_config_word(pdev, addr, speed_p[pio]); -+ pci_write_config_word(pdev, tfaddr, speed_t[lowest_pio]); -+ -+ pci_read_config_word(pdev, tfaddr-2, ®); -+ reg &= ~0x0200; /* Clear IORDY */ -+ if (ata_pio_need_iordy(adev)) -+ reg |= 0x0200; /* Enable IORDY */ -+ pci_write_config_word(pdev, tfaddr-2, reg); -+} -+ -+/** -+ * sil680_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Program the MWDMA/UDMA modes for the sil680 k -+ * chipset. The MWDMA mode values are pulled from a lookup table -+ * while the chipset uses mode number for UDMA. -+ */ -+ -+static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ static u8 ultra_table[2][7] = { -+ { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01, 0xFF }, /* 100MHz */ -+ { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }, /* 133Mhz */ -+ }; -+ static u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 }; -+ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ unsigned long ma = sil680_seldev(ap, adev, 0x08); -+ unsigned long ua = sil680_seldev(ap, adev, 0x0C); -+ unsigned long addr_mask = 0x80 + 4 * ap->hard_port_no; -+ int port_shift = adev->devno * 4; -+ u8 scsc, mode; -+ u16 multi, ultra; -+ -+ pci_read_config_byte(pdev, 0x8A, &scsc); -+ pci_read_config_byte(pdev, addr_mask, &mode); -+ pci_read_config_word(pdev, ma, &multi); -+ pci_read_config_word(pdev, ua, &ultra); -+ -+ /* Mask timing bits */ -+ ultra &= ~0x3F; -+ mode &= ~(0x03 << port_shift); -+ -+ /* Extract scsc */ -+ scsc = (scsc & 0x30) ? 1: 0; -+ -+ if (adev->dma_mode >= XFER_UDMA_0) { -+ multi = 0x10C1; -+ ultra |= ultra_table[scsc][adev->dma_mode - XFER_UDMA_0]; -+ mode |= (0x03 << port_shift); -+ } else { -+ multi = dma_table[adev->dma_mode - XFER_MW_DMA_0]; -+ mode |= (0x02 << port_shift); -+ } -+ pci_write_config_byte(pdev, addr_mask, mode); -+ pci_write_config_word(pdev, ma, multi); -+ pci_write_config_word(pdev, ua, ultra); -+} -+ -+static struct scsi_host_template sil680_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations sil680_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sil680_set_piomode, -+ .set_dmamode = sil680_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sil680_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &sil680_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, -+ .port_ops = &sil680_port_ops -+ }; -+ static struct ata_port_info info_slow = { -+ .sht = &sil680_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &sil680_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = {&info, &info}; -+ static int printed_version; -+ u32 class_rev = 0; -+ u8 tmpbyte = 0; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); -+ -+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); -+ class_rev &= 0xff; -+ /* FIXME: double check */ -+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255); -+ -+ pci_write_config_byte(pdev, 0x80, 0x00); -+ pci_write_config_byte(pdev, 0x84, 0x00); -+ -+ pci_read_config_byte(pdev, 0x8A, &tmpbyte); -+ -+ printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", -+ tmpbyte & 1, tmpbyte & 0x30); -+ -+ switch(tmpbyte & 0x30) { -+ case 0x00: -+ /* 133 clock attempt to force it on */ -+ pci_write_config_byte(pdev, 0x8A, tmpbyte|0x10); -+ break; -+ case 0x30: -+ /* if clocking is disabled */ -+ /* 133 clock attempt to force it on */ -+ pci_write_config_byte(pdev, 0x8A, tmpbyte & ~0x20); -+ break; -+ case 0x10: -+ /* 133 already */ -+ break; -+ case 0x20: -+ /* BIOS set PCI x2 clocking */ -+ break; -+ } -+ -+ pci_read_config_byte(pdev, 0x8A, &tmpbyte); -+ printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", -+ tmpbyte & 1, tmpbyte & 0x30); -+ if ((tmpbyte & 0x30) == 0) -+ port_info[0] = port_info[1] = &info_slow; -+ -+ pci_write_config_byte(pdev, 0xA1, 0x72); -+ pci_write_config_word(pdev, 0xA2, 0x328A); -+ pci_write_config_dword(pdev, 0xA4, 0x62DD62DD); -+ pci_write_config_dword(pdev, 0xA8, 0x43924392); -+ pci_write_config_dword(pdev, 0xAC, 0x40094009); -+ pci_write_config_byte(pdev, 0xB1, 0x72); -+ pci_write_config_word(pdev, 0xB2, 0x328A); -+ pci_write_config_dword(pdev, 0xB4, 0x62DD62DD); -+ pci_write_config_dword(pdev, 0xB8, 0x43924392); -+ pci_write_config_dword(pdev, 0xBC, 0x40094009); -+ -+ switch(tmpbyte & 0x30) { -+ case 0x00: printk(KERN_INFO "sil680: 100MHz clock.\n");break; -+ case 0x10: printk(KERN_INFO "sil680: 133MHz clock.\n");break; -+ case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; -+ /* This last case is _NOT_ ok */ -+ case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); -+ return -EIO; -+ } -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id sil680[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680), }, -+ { 0, }, -+}; -+ -+static struct pci_driver sil680_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = sil680, -+ .probe = sil680_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init sil680_init(void) -+{ -+ return pci_register_driver(&sil680_pci_driver); -+} -+ -+ -+static void __exit sil680_exit(void) -+{ -+ pci_unregister_driver(&sil680_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for SI680 PATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, sil680); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(sil680_init); -+module_exit(sil680_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sis.c linux-2.6.16-rc6/drivers/scsi/pata_sis.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sis.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_sis.c 2006-02-28 16:51:31.000000000 +0000 -@@ -0,0 +1,982 @@ -+/* -+ * pata_sis.c - SiS ATA driver -+ * -+ * (C) 2005 Red Hat <alan@redhat.com> -+ * -+ * Based upon linux/drivers/ide/pci/sis5513.c -+ * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> -+ * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer -+ * Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz> -+ * SiS Taiwan : for direct support and hardware. -+ * Daniela Engert : for initial ATA100 advices and numerous others. -+ * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : -+ * for checking code correctness, providing patches. -+ * Original tests and design on the SiS620 chipset. -+ * ATA100 tests and design on the SiS735 chipset. -+ * ATA16/33 support from specs -+ * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw> -+ * -+ * -+ * TODO -+ * Check MWDMA on drives that don't support MWDMA speed pio cycles ? -+ * More Testing -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <linux/device.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+#include <linux/ata.h> -+ -+#define DRV_NAME "pata_sis" -+#define DRV_VERSION "0.2" -+ -+struct sis_chipset { -+ u16 device; /* PCI host ID */ -+ struct ata_port_info *info; /* Info block */ -+ /* Probably add family, cable detect type etc here to clean -+ up code later */ -+}; -+ -+/** -+ * sis_133_cable_detect - check for 40/80 pin -+ * @ap: Port -+ * -+ * Perform cable detection for the later UDMA133 capable -+ * SiS chipset. -+ */ -+ -+static int sis_133_cable_detect(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u16 tmp; -+ -+ pci_read_config_word(pdev, 0x50 + 2 * ap->hard_port_no, &tmp); -+ if (tmp & 0x8000) -+ return ATA_CBL_PATA40; -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * sis_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_133_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits sis_enable_bits[] = { -+ { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ -+ { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = sis_133_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+ -+/** -+ * sis_66_cable_detect - check for 40/80 pin -+ * @ap: Port -+ * -+ * Perform cable detection on the UDMA66, UDMA100 and early UDMA133 -+ * SiS IDE controllers. -+ */ -+ -+static int sis_66_cable_detect(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 tmp; -+ -+ pci_read_config_byte(pdev, 0x48, &tmp); -+ tmp >>= ap->hard_port_no; -+ if (tmp & 0x10) -+ return ATA_CBL_PATA40; -+ return ATA_CBL_PATA80; -+} -+ -+/** -+ * sis_66_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_66_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits sis_enable_bits[] = { -+ { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ -+ { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = sis_66_cable_detect(ap); -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+ -+/** -+ * sis_old_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_old_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits sis_enable_bits[] = { -+ { 0x4aU, 1U, 0x02UL, 0x02UL }, /* port 0 */ -+ { 0x4aU, 1U, 0x04UL, 0x04UL }, /* port 1 */ -+ }; -+ -+ if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * sis_set_fifo - Set RWP fifo bits for this device -+ * @ap: Port -+ * @adev: Device -+ * -+ * SIS chipsets implement prefetch/postwrite bits for each device -+ * on both channels. This functionality is not ATAPI compatible and -+ * must be configured according to the class of device present -+ */ -+ -+static void sis_set_fifo(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u8 reg4b; -+ u8 mask = 0x11; -+ -+ mask <<= (2 * ap->hard_port_no); -+ mask <<= adev->devno; -+ -+ pci_read_config_byte(pdev, 0x4B, ®4b); -+ reg4b &= ~mask; -+ -+ /* Enable for ATA (disk) only */ -+ if (adev->class == ATA_DEV_ATA) -+ reg4b |= mask; -+ pci_write_config_byte(pdev, 0x4B, reg4b); -+} -+ -+/** -+ * sis_old_set_piomode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring for. -+ * -+ * Set PIO mode for device, in host controller PCI config space. This -+ * function handles PIO set up for all chips that are pre ATA100 and -+ * also early ATA100 devices. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_old_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ u8 t1, t2; -+ int speed = adev->pio_mode - XFER_PIO_0; -+ -+ const u8 active[] = { 0x00, 0x07, 0x04, 0x03, 0x01 }; -+ const u8 recovery[] = { 0x00, 0x06, 0x04, 0x03, 0x03 }; -+ -+ sis_set_fifo(ap, adev); -+ -+ pci_read_config_byte(pdev, port, &t1); -+ pci_read_config_byte(pdev, port + 1, &t2); -+ -+ t1 &= ~0x0F; /* Clear active/recovery timings */ -+ t2 &= ~0x07; -+ -+ t1 |= active[speed]; -+ t2 |= recovery[speed]; -+ -+ pci_write_config_byte(pdev, port, t1); -+ pci_write_config_byte(pdev, port + 1, t2); -+} -+ -+/** -+ * sis_100_set_pioode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring for. -+ * -+ * Set PIO mode for device, in host controller PCI config space. This -+ * function handles PIO set up for ATA100 devices and early ATA133. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_100_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ int speed = adev->pio_mode - XFER_PIO_0; -+ -+ const u8 actrec[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; -+ -+ sis_set_fifo(ap, adev); -+ -+ pci_write_config_byte(pdev, port, actrec[speed]); -+} -+ -+/** -+ * sis_133_set_pioode - Initialize host controller PATA PIO timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device we are configuring for. -+ * -+ * Set PIO mode for device, in host controller PCI config space. This -+ * function handles PIO set up for the later ATA133 devices. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_133_set_piomode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int port = 0x40; -+ u32 t1; -+ u32 reg54; -+ int speed = adev->pio_mode - XFER_PIO_0; -+ -+ const u32 timing133[] = { -+ 0x28269000, /* Recovery << 24 | Act << 16 | Ini << 12 */ -+ 0x0C266000, -+ 0x04263000, -+ 0x0C0A3000, -+ 0x05093000 -+ }; -+ const u32 timing100[] = { -+ 0x1E1C6000, /* Recovery << 24 | Act << 16 | Ini << 12 */ -+ 0x091C4000, -+ 0x031C2000, -+ 0x09072000, -+ 0x04062000 -+ }; -+ -+ sis_set_fifo(ap, adev); -+ -+ pci_read_config_dword(pdev, 0x54, ®54); -+ if (reg54 & 0x40000000) -+ port = 0x70; -+ port += 8 * ap->hard_port_no + 4 * adev->devno; -+ -+ pci_read_config_dword(pdev, port, &t1); -+ t1 &= 0xC0C00FFF; /* Mask out timing */ -+ -+ if (t1 & 0x08) /* 100 or 133 ? */ -+ t1 |= timing133[speed]; -+ else -+ t1 |= timing100[speed]; -+ pci_write_config_byte(pdev, port, t1); -+} -+ -+/** -+ * sis_old_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * Handles pre UDMA and UDMA33 devices. Supports MWDMA as well unlike -+ * the old ide/pci driver. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ int drive_pci = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ u16 timing; -+ -+ const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 }; -+ const u16 udma_bits[] = { -+ 0xE000, 0xC000, 0xA000 -+ }; -+ -+ pci_read_config_word(pdev, drive_pci, &timing); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ /* bits 3-0 hold recovery timing bits 8-10 active timing and -+ the higer bits are dependant on the device */ -+ timing &= ~ 0x870F; -+ timing |= mwdma_bits[speed]; -+ pci_write_config_word(pdev, drive_pci, timing); -+ } else { -+ /* Bit 15 is UDMA on/off, bit 13-14 are cycle time */ -+ speed = adev->dma_mode - XFER_UDMA_0; -+ timing &= ~0x6000; -+ timing |= udma_bits[speed]; -+ } -+} -+ -+/** -+ * sis_66_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * Handles UDMA66 and early UDMA100 devices. Supports MWDMA as well unlike -+ * the old ide/pci driver. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ int drive_pci = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ u16 timing; -+ -+ const u16 mwdma_bits[] = { 0x707, 0x202, 0x202 }; -+ const u16 udma_bits[] = { 0xF000, 0xD000, 0xB000, 0xA000, 0x9000}; -+ -+ pci_read_config_word(pdev, drive_pci, &timing); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ /* bits 3-0 hold recovery timing bits 8-10 active timing and -+ the higer bits are dependant on the device, bit 15 udma */ -+ timing &= ~ 0x870F; -+ timing |= mwdma_bits[speed]; -+ } else { -+ /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ -+ speed = adev->dma_mode - XFER_UDMA_0; -+ timing &= ~0x6000; -+ timing |= udma_bits[speed]; -+ } -+ pci_write_config_word(pdev, drive_pci, timing); -+} -+ -+/** -+ * sis_100_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * Handles UDMA66 and early UDMA100 devices. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_100_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ int drive_pci = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ u16 timing; -+ -+ const u16 udma_bits[] = { 0x8B00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100}; -+ -+ pci_read_config_word(pdev, drive_pci, &timing); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */ -+ } else { -+ /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ -+ speed = adev->dma_mode - XFER_UDMA_0; -+ timing &= ~0x0F00; -+ timing |= udma_bits[speed]; -+ } -+ pci_write_config_word(pdev, drive_pci, timing); -+} -+ -+/** -+ * sis_133_early_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * Handles early SiS 961 bridges. Supports MWDMA as well unlike -+ * the old ide/pci driver. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_133_early_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ int drive_pci = 0x40 + 4 * ap->hard_port_no + 2 * adev->devno; -+ u16 timing; -+ -+ const u16 udma_bits[] = { 0x8F00, 0x8A00, 0x8700, 0x8500, 0x8300, 0x8200, 0x8100}; -+ -+ pci_read_config_word(pdev, drive_pci, &timing); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ /* NOT SUPPORTED YET: NEED DATA SHEET. DITTO IN OLD DRIVER */ -+ } else { -+ /* Bit 15 is UDMA on/off, bit 12-14 are cycle time */ -+ speed = adev->dma_mode - XFER_UDMA_0; -+ timing &= ~0x0F00; -+ timing |= udma_bits[speed]; -+ } -+ pci_write_config_word(pdev, drive_pci, timing); -+} -+ -+/** -+ * sis_133_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: Device to program -+ * -+ * Set UDMA/MWDMA mode for device, in host controller PCI config space. -+ * Handles early SiS 961 bridges. Supports MWDMA as well unlike -+ * the old ide/pci driver. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void sis_133_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ int speed = adev->dma_mode - XFER_MW_DMA_0; -+ int port = 0x40; -+ u32 t1; -+ u32 reg54; -+ -+ /* bits 4- cycle time 8 - cvs time */ -+ const u32 timing_u100[] = { 0x6B0, 0x470, 0x350, 0x140, 0x120, 0x110, 0x000 }; -+ const u32 timing_u133[] = { 0x9F0, 0x6A0, 0x470, 0x250, 0x230, 0x220, 0x210 }; -+ -+ pci_read_config_dword(pdev, 0x54, ®54); -+ if (reg54 & 0x40000000) -+ port = 0x70; -+ port += 8 * ap->hard_port_no + 4 * adev->devno; -+ -+ pci_read_config_dword(pdev, port, &t1); -+ -+ if (adev->dma_mode < XFER_UDMA_0) { -+ t1 &= ~0x00000004; -+ /* FIXME: need data sheet to add MWDMA here. Also lacking on -+ ide/pci driver */ -+ } else { -+ speed = adev->dma_mode - XFER_UDMA_0; -+ /* if & 8 no UDMA133 - need info for ... */ -+ t1 &= ~0x00000FF0; -+ t1 |= 0x00000004; -+ if (t1 & 0x08) -+ t1 |= timing_u133[speed]; -+ else -+ t1 |= timing_u100[speed]; -+ } -+ pci_write_config_dword(pdev, port, t1); -+} -+ -+static struct scsi_host_template sis_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static const struct ata_port_operations sis_133_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sis_133_set_piomode, -+ .set_dmamode = sis_133_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sis_133_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations sis_133_early_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sis_100_set_piomode, -+ .set_dmamode = sis_133_early_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sis_66_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations sis_100_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sis_100_set_piomode, -+ .set_dmamode = sis_100_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sis_66_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations sis_66_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sis_old_set_piomode, -+ .set_dmamode = sis_66_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sis_66_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations sis_old_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sis_old_set_piomode, -+ .set_dmamode = sis_old_set_dmamode, -+ -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sis_old_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static struct ata_port_info sis_info = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, -+ .udma_mask = 0, -+ .port_ops = &sis_old_ops, -+}; -+static struct ata_port_info sis_info33 = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, -+ .udma_mask = ATA_UDMA2, /* UDMA 33 */ -+ .port_ops = &sis_old_ops, -+}; -+static struct ata_port_info sis_info66 = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .udma_mask = ATA_UDMA4, /* UDMA 66 */ -+ .port_ops = &sis_66_ops, -+}; -+static struct ata_port_info sis_info100 = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .udma_mask = ATA_UDMA5, -+ .port_ops = &sis_100_ops, -+}; -+static struct ata_port_info sis_info100_early = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .udma_mask = ATA_UDMA5, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .port_ops = &sis_66_ops, -+}; -+static struct ata_port_info sis_info133 = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &sis_133_ops, -+}; -+static struct ata_port_info sis_info133_early = { -+ .sht = &sis_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &sis_133_early_ops, -+}; -+ -+ -+static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis) -+{ -+ u16 regw; -+ u8 reg; -+ -+ if (sis->info == &sis_info133) { -+ pci_read_config_word(pdev, 0x50, ®w); -+ if (regw & 0x08) -+ pci_write_config_word(pdev, 0x50, regw & ~0x08); -+ pci_read_config_word(pdev, 0x52, ®w); -+ if (regw & 0x08) -+ pci_write_config_word(pdev, 0x52, regw & ~0x08); -+ return; -+ } -+ -+ if (sis->info == &sis_info133_early || sis->info == &sis_info100) { -+ /* Fix up latency */ -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); -+ /* Set compatibility bit */ -+ pci_read_config_byte(pdev, 0x49, ®); -+ if (!(reg & 0x01)) -+ pci_write_config_byte(pdev, 0x49, reg | 0x01); -+ return; -+ } -+ -+ if (sis->info == &sis_info66 || sis->info == &sis_info100_early) { -+ /* Fix up latency */ -+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80); -+ /* Set compatibility bit */ -+ pci_read_config_byte(pdev, 0x52, ®); -+ if (!(reg & 0x04)) -+ pci_write_config_byte(pdev, 0x52, reg | 0x04); -+ return; -+ } -+ -+ if (sis->info == &sis_info33) { -+ pci_read_config_byte(pdev, PCI_CLASS_PROG, ®); -+ if (( reg & 0x0F ) != 0x00) -+ pci_write_config_byte(pdev, PCI_CLASS_PROG, reg & 0xF0); -+ /* Fall through to ATA16 fixup below */ -+ } -+ -+ if (sis->info == &sis_info || sis->info == &sis_info33) { -+ /* force per drive recovery and active timings -+ needed on ATA_33 and below chips */ -+ pci_read_config_byte(pdev, 0x52, ®); -+ if (!(reg & 0x08)) -+ pci_write_config_byte(pdev, 0x52, reg|0x08); -+ return; -+ } -+ -+ BUG(); -+} -+ -+/** -+ * sis_init_one - Register SiS ATA PCI device with kernel services -+ * @pdev: PCI device to register -+ * @ent: Entry in sis_pci_tbl matching with @pdev -+ * -+ * Called from kernel PCI layer. We probe for combined mode (sigh), -+ * and then hand over control to libata, for it to do the rest. -+ * -+ * LOCKING: -+ * Inherited from PCI layer (may sleep). -+ * -+ * RETURNS: -+ * Zero on success, or -ERRNO value. -+ */ -+ -+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) -+{ -+ static int printed_version; -+ static struct ata_port_info *port_info[2]; -+ struct ata_port_info *port; -+ struct pci_dev *host; -+ struct sis_chipset *chipset = NULL; -+ -+ static struct sis_chipset sis_chipsets[] = { -+ { 0x0745, &sis_info100 }, -+ { 0x0735, &sis_info100 }, -+ { 0x0733, &sis_info100 }, -+ { 0x0635, &sis_info100 }, -+ { 0x0633, &sis_info100 }, -+ -+ { 0x0730, &sis_info100_early }, /* 100 with ATA 66 layout */ -+ { 0x0550, &sis_info100_early }, /* 100 with ATA 66 layout */ -+ -+ { 0x0640, &sis_info66 }, -+ { 0x0630, &sis_info66 }, -+ { 0x0620, &sis_info66 }, -+ { 0x0540, &sis_info66 }, -+ { 0x0530, &sis_info66 }, -+ -+ { 0x5600, &sis_info33 }, -+ { 0x5598, &sis_info33 }, -+ { 0x5597, &sis_info33 }, -+ { 0x5591, &sis_info33 }, -+ { 0x5582, &sis_info33 }, -+ { 0x5581, &sis_info33 }, -+ -+ { 0x5596, &sis_info }, -+ { 0x5571, &sis_info }, -+ { 0x5517, &sis_info }, -+ { 0x5511, &sis_info }, -+ -+ {0} -+ }; -+ static struct sis_chipset sis133_early = { -+ 0x0, &sis_info133_early -+ }; -+ static struct sis_chipset sis133 = { -+ 0x0, &sis_info133 -+ }; -+ static struct sis_chipset sis100_early = { -+ 0x0, &sis_info100_early -+ }; -+ static struct sis_chipset sis100 = { -+ 0x0, &sis_info100 -+ }; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, -+ "version " DRV_VERSION "\n"); -+ -+ /* We have to find the bridge first */ -+ -+ for (chipset = &sis_chipsets[0]; chipset->device; chipset++) { -+ host = pci_get_device(0x1039, chipset->device, NULL); -+ if (host != NULL) { -+ if (chipset->device == 0x630) { /* SIS630 */ -+ u8 host_rev; -+ pci_read_config_byte(host, PCI_REVISION_ID, &host_rev); -+ if (host_rev >= 0x30) /* 630 ET */ -+ chipset = &sis100_early; -+ } -+ break; -+ } -+ } -+ -+ /* Look for concealed bridges */ -+ if (host == NULL) { -+ /* Second check */ -+ u32 idemisc; -+ u16 trueid; -+ -+ /* Disable ID masking and register remapping then -+ see what the real ID is */ -+ -+ pci_read_config_dword(pdev, 0x54, &idemisc); -+ pci_write_config_dword(pdev, 0x54, idemisc & 0x7fffffff); -+ pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid); -+ pci_write_config_dword(pdev, 0x54, idemisc); -+ -+ switch(trueid) { -+ case 0x5518: /* SIS 962/963 */ -+ chipset = &sis133; -+ if ((idemisc & 0x40000000) == 0) { -+ pci_write_config_dword(pdev, 0x54, idemisc | 0x40000000); -+ printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n"); -+ } -+ break; -+ case 0x0180: /* SIS 965/965L */ -+ chipset = &sis133; -+ break; -+ case 0x1180: /* SIS 966/966L */ -+ chipset = &sis133; -+ break; -+ } -+ } -+ -+ /* Further check */ -+ if (chipset == NULL) { -+ struct pci_dev *lpc_bridge; -+ u16 trueid; -+ u8 prefctl; -+ u8 idecfg; -+ u8 sbrev; -+ -+ /* Try the second unmasking technique */ -+ pci_read_config_byte(pdev, 0x4a, &idecfg); -+ pci_write_config_byte(pdev, 0x4a, idecfg | 0x10); -+ pci_read_config_word(pdev, PCI_DEVICE_ID, &trueid); -+ pci_write_config_byte(pdev, 0x4a, idecfg); -+ -+ switch(trueid) { -+ case 0x5517: -+ lpc_bridge = pci_get_slot(0x00, 0x10); /* Bus 0 Dev 2 Fn 0 */ -+ if (lpc_bridge == NULL) -+ break; -+ pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); -+ pci_read_config_byte(pdev, 0x49, &prefctl); -+ pci_dev_put(lpc_bridge); -+ -+ if (sbrev == 0x10 && (prefctl & 0x80)) { -+ chipset = &sis133_early; -+ break; -+ } -+ chipset = &sis100; -+ break; -+ } -+ } -+ pci_dev_put(host); -+ -+ /* No chipset info, no support */ -+ if (chipset == NULL) -+ return -ENODEV; -+ -+ port = chipset->info; -+ port->private_data = chipset; -+ -+ sis_fixup(pdev, chipset); -+ -+ port_info[0] = port_info[1] = port; -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id sis_pci_tbl[] = { -+ { 0x1039, 0x5513, PCI_ANY_ID, PCI_ANY_ID, }, -+ { 0x1039, 0x5518, PCI_ANY_ID, PCI_ANY_ID, }, -+ { } /* terminate list */ -+}; -+ -+static struct pci_driver sis_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = sis_pci_tbl, -+ .probe = sis_init_one, -+ .remove = ata_pci_remove_one, -+}; -+ -+static int __init sis_init(void) -+{ -+ return pci_register_driver(&sis_pci_driver); -+} -+ -+static void __exit sis_exit(void) -+{ -+ pci_unregister_driver(&sis_pci_driver); -+} -+ -+ -+module_init(sis_init); -+module_exit(sis_exit); -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("SCSI low-level driver for SiS ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, sis_pci_tbl); -+MODULE_VERSION(DRV_VERSION); -+ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sl82c105.c linux-2.6.16-rc6/drivers/scsi/pata_sl82c105.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_sl82c105.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_sl82c105.c 2006-02-16 15:36:32.000000000 +0000 -@@ -0,0 +1,376 @@ -+/* -+ * pata_sl82c105.c - SL82C105 PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Based in part on linux/drivers/ide/pci/sl82c105.c -+ * SL82C105/Winbond 553 IDE driver -+ * -+ * and in part on the documentation and errata sheet -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_sl82c105" -+#define DRV_VERSION "0.1.1" -+ -+enum { -+ /* -+ * SL82C105 PCI config register 0x40 bits. -+ */ -+ CTRL_IDE_IRQB = (1 << 30), -+ CTRL_IDE_IRQA = (1 << 28), -+ CTRL_LEGIRQ = (1 << 11), -+ CTRL_P1F16 = (1 << 5), -+ CTRL_P1EN = (1 << 4), -+ CTRL_P0F16 = (1 << 1), -+ CTRL_P0EN = (1 << 0) -+}; -+ -+static void sl82c105_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits sl82c105_enable_bits[] = { -+ { 0x40, 1, 0x01, 0x01 }, -+ { 0x40, 1, 0x10, 0x10 } -+ }; -+ -+ if (ap->hard_port_no && !pci_test_config_bits(pdev, &sl82c105_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ dev_printk(KERN_INFO, &pdev->dev, "port disabled. ignoring.\n"); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+ -+/** -+ * sl82c105_configure_piomode - set chip PIO timing -+ * @ap: ATA interface -+ * @adev: ATA device -+ * @pio: PIO mode -+ * -+ * Called to do the PIO mode setup. Our timing registers are shared -+ * so a configure_dmamode call will undo any work we do here and vice -+ * versa -+ */ -+ -+static void sl82c105_configure_piomode(struct ata_port *ap, struct ata_device *adev, int pio) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static u16 pio_timing[5] = { -+ 0x50D, 0x407, 0x304, 0x242, 0x240 -+ }; -+ u16 dummy; -+ int timing = 0x44 + 8 * ap->hard_port_no + 4 * adev->devno; -+ -+ pci_write_config_word(pdev, timing, pio_timing[pio]); -+ /* Can we lose this oddity of the old driver */ -+ pci_read_config_word(pdev, timing, &dummy); -+} -+ -+/** -+ * sl82c105_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the PIO mode setup. Our timing registers are shared -+ * but we want to set the PIO timing by default. -+ */ -+ -+static void sl82c105_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ sl82c105_configure_piomode(ap, adev, adev->pio_mode - XFER_PIO_0); -+} -+ -+/** -+ * sl82c105_configure_dmamode - set DMA mode in chip -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Load DMA cycle times into the chip ready for a DMA transfer -+ * to occur. -+ */ -+ -+static void sl82c105_configure_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static u16 dma_timing[3] = { -+ 0x707, 0x201, 0x200 -+ }; -+ u16 dummy; -+ int timing = 0x44 + 8 * ap->hard_port_no + 4 * adev->devno; -+ int dma = adev->dma_mode - XFER_MW_DMA_0; -+ -+ pci_write_config_word(pdev, timing, dma_timing[dma]); -+ /* Can we lose this oddity of the old driver */ -+ pci_read_config_word(pdev, timing, &dummy); -+} -+ -+/** -+ * sl82c105_set_dmamode - set initial DMA mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Called to do the DMA mode setup. This replaces the PIO timings -+ * for the device in question. Set appropriate PIO timings not DMA -+ * timings at this point. -+ */ -+ -+static void sl82c105_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ switch(adev->dma_mode) { -+ case XFER_MW_DMA_0: -+ sl82c105_configure_piomode(ap, adev, 1); -+ break; -+ case XFER_MW_DMA_1: -+ sl82c105_configure_piomode(ap, adev, 3); -+ break; -+ case XFER_MW_DMA_2: -+ sl82c105_configure_piomode(ap, adev, 3); -+ break; -+ default: -+ BUG(); -+ } -+} -+ -+/** -+ * sl82c105_reset_engine - Reset the DMA engine -+ * @ap: ATA interface -+ * -+ * The sl82c105 has some serious problems with the DMA engine -+ * when transfers don't run as expected or ATAPI is used. The -+ * recommended fix is to reset the engine each use using a chip -+ * test register. -+ */ -+ -+static void sl82c105_reset_engine(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u16 val; -+ -+ pci_read_config_word(pdev, 0x7E, &val); -+ pci_write_config_word(pdev, 0x7E, val | 4); -+ pci_write_config_word(pdev, 0x7E, val & ~4); -+} -+ -+/** -+ * sl82c105_bmdma_start - DMA engine begin -+ * @qc: ATA command -+ * -+ * Reset the DMA engine each use as recommended by the errata -+ * document. -+ * -+ * FIXME: if we switch clock at BMDMA start/end we might get better -+ * PIO performance on DMA capable devices. -+ */ -+ -+static void sl82c105_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ -+ sl82c105_reset_engine(ap); -+ -+ /* Set the clocks for DMA */ -+ sl82c105_configure_dmamode(ap, qc->dev); -+ /* Activate DMA */ -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * sl82c105_bmdma_end - DMA engine stop -+ * @qc: ATA command -+ * -+ * Reset the DMA engine each use as recommended by the errata -+ * document. -+ * -+ * This function is also called to turn off DMA when a timeout occurs -+ * during DMA operation. In both cases we need to reset the engine, -+ * so no actual eng_timeout handler is required. -+ * -+ * We assume bmdma_stop is always called if bmdma_start as called. If -+ * not then we may need to wrap qc_issue. -+ */ -+ -+static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ struct ata_port *ap = qc->ap; -+ -+ ata_bmdma_stop(qc); -+ sl82c105_reset_engine(ap); -+ -+ /* This will redo the initial setup of the DMA device to matching -+ PIO timings */ -+ sl82c105_set_dmamode(ap, qc->dev); -+} -+ -+static struct scsi_host_template sl82c105_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations sl82c105_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = sl82c105_set_piomode, -+ .set_dmamode = sl82c105_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = sl82c105_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = sl82c105_bmdma_start, -+ .bmdma_stop = sl82c105_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * sl82c105_bridge_revision - find bridge version -+ * @pdev: PCI device for the ATA function -+ * -+ * Locates the PCI bridge associated with the ATA function and -+ * providing it is a Winbond 553 reports the revision. If it cannot -+ * find a revision or the right device it returns -1 -+ */ -+ -+static int sl82c105_bridge_revision(struct pci_dev *pdev) -+{ -+ struct pci_dev *bridge; -+ u8 rev; -+ -+ /* -+ * The bridge should be part of the same device, but function 0. -+ */ -+ bridge = pci_get_slot(pdev->bus, -+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); -+ if (!bridge) -+ return -1; -+ -+ /* -+ * Make sure it is a Winbond 553 and is an ISA bridge. -+ */ -+ if (bridge->vendor != PCI_VENDOR_ID_WINBOND || -+ bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || -+ bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) { -+ pci_dev_put(bridge); -+ return -1; -+ } -+ /* -+ * We need to find function 0's revision, not function 1 -+ */ -+ pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); -+ -+ pci_dev_put(bridge); -+ return rev; -+} -+ -+ -+static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info_dma = { -+ .sht = &sl82c105_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &sl82c105_port_ops -+ }; -+ static struct ata_port_info info_early = { -+ .sht = &sl82c105_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .port_ops = &sl82c105_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info_early, &info_early }; -+ u32 val; -+ int rev; -+ -+ rev = sl82c105_bridge_revision(dev); -+ -+ if (rev == -1) -+ dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Unable to find bridge, disabling DMA.\n"); -+ else if (rev <= 5) -+ dev_printk(KERN_WARNING, &dev->dev, "pata_sl82c105: Early bridge revision, no DMA available.\n"); -+ else { -+ port_info[0] = &info_dma; -+ port_info[1] = &info_dma; -+ } -+ -+ pci_read_config_dword(dev, 0x40, &val); -+ val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; -+ pci_write_config_dword(dev, 0x40, val); -+ -+ -+ return ata_pci_init_one(dev, port_info, 1); /* For now */ -+} -+ -+static struct pci_device_id sl82c105[] = { -+ { PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0, }, -+}; -+ -+static struct pci_driver sl82c105_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = sl82c105, -+ .probe = sl82c105_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init sl82c105_init(void) -+{ -+ return pci_register_driver(&sl82c105_pci_driver); -+} -+ -+ -+static void __exit sl82c105_exit(void) -+{ -+ pci_unregister_driver(&sl82c105_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Sl82c105"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, sl82c105); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(sl82c105_init); -+module_exit(sl82c105_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_triflex.c linux-2.6.16-rc6/drivers/scsi/pata_triflex.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_triflex.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_triflex.c 2006-02-16 15:36:23.000000000 +0000 -@@ -0,0 +1,268 @@ -+/* -+ * pata_triflex.c - Compaq PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * based upon -+ * -+ * triflex.c -+ * -+ * IDE Chipset driver for the Compaq TriFlex IDE controller. -+ * -+ * Known to work with the Compaq Workstation 5x00 series. -+ * -+ * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. -+ * Author: Torben Mathiasen <torben.mathiasen@hp.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * Loosely based on the piix & svwks drivers. -+ * -+ * Documentation: -+ * Not publically available. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_triflex" -+#define DRV_VERSION "0.2.1" -+ -+static void triflex_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static struct pci_bits triflex_enable_bits[] = { -+ { 0x80, 1, 0x01, 0x01 }, -+ { 0x80, 1, 0x02, 0x02 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * triflex_load_timing - timing configuration -+ * @ap: ATA interface -+ * @adev: Device on the bus -+ * @speed: speed to configure -+ * -+ * The Triflex has one set of timings per device per channel. This -+ * means we must do some switching. As the PIO and DMA timings don't -+ * match we have to do some reloading unlike PIIX devices where tuning -+ * tricks can avoid it. -+ */ -+ -+static void triflex_load_timing(struct ata_port *ap, struct ata_device *adev, int speed) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 timing = 0; -+ u32 triflex_timing, old_triflex_timing; -+ int channel_offset = ap->hard_port_no ? 0x74: 0x70; -+ unsigned int is_slave = (adev->devno != 0); -+ -+ -+ pci_read_config_dword(pdev, channel_offset, &old_triflex_timing); -+ triflex_timing = old_triflex_timing; -+ -+ switch(speed) -+ { -+ case XFER_MW_DMA_2: -+ timing = 0x0103;break; -+ case XFER_MW_DMA_1: -+ timing = 0x0203;break; -+ case XFER_MW_DMA_0: -+ timing = 0x0808;break; -+ case XFER_SW_DMA_2: -+ case XFER_SW_DMA_1: -+ case XFER_SW_DMA_0: -+ timing = 0x0F0F;break; -+ case XFER_PIO_4: -+ timing = 0x0202;break; -+ case XFER_PIO_3: -+ timing = 0x0204;break; -+ case XFER_PIO_2: -+ timing = 0x0404;break; -+ case XFER_PIO_1: -+ timing = 0x0508;break; -+ case XFER_PIO_0: -+ timing = 0x0808;break; -+ default: -+ BUG(); -+ } -+ triflex_timing &= ~ (0xFFFF << (16 * is_slave)); -+ triflex_timing |= (timing << (16 * is_slave)); -+ -+ if (triflex_timing != old_triflex_timing) -+ pci_write_config_dword(pdev, channel_offset, triflex_timing); -+} -+ -+/** -+ * triflex_set_piomode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * Use the timing loader to set up the PIO mode. We have to do this -+ * because DMA start/stop will only be called once DMA occurs. If there -+ * has been no DMA then the PIO timings are still needed. -+ */ -+static void triflex_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ triflex_load_timing(ap, adev, adev->pio_mode); -+} -+ -+/** -+ * triflex_dma_start - DMA start callback -+ * @qc: Command in progress -+ * -+ * Usually drivers set the DMA timing at the point the set_dmamode call -+ * is made. Triflex however requires we load new timings on the -+ * transition or keep matching PIO/DMA pairs (ie MWDMA2/PIO4 etc). -+ * We load the DMA timings just before starting DMA and then restore -+ * the PIO timing when the DMA is finished. -+ */ -+ -+static void triflex_bmdma_start(struct ata_queued_cmd *qc) -+{ -+ triflex_load_timing(qc->ap, qc->dev, qc->dev->dma_mode); -+ ata_bmdma_start(qc); -+} -+ -+/** -+ * triflex_dma_stop - DMA stop callback -+ * @ap: ATA interface -+ * @adev: ATA device -+ * -+ * We loaded new timings in dma_start, as a result we need to restore -+ * the PIO timings in dma_stop so that the next command issue gets the -+ * right clock values. -+ */ -+ -+static void triflex_bmdma_stop(struct ata_queued_cmd *qc) -+{ -+ ata_bmdma_stop(qc); -+ triflex_load_timing(qc->ap, qc->dev, qc->dev->pio_mode); -+} -+ -+static struct scsi_host_template triflex_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations triflex_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = triflex_set_piomode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = triflex_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = triflex_bmdma_start, -+ .bmdma_stop = triflex_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ static struct ata_port_info info = { -+ .sht = &triflex_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &triflex_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ static int printed_version; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); -+ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static const struct pci_device_id triflex[] = { -+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE, -+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -+ { 0, }, -+}; -+ -+static struct pci_driver triflex_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = triflex, -+ .probe = triflex_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init triflex_init(void) -+{ -+ return pci_register_driver(&triflex_pci_driver); -+} -+ -+ -+static void __exit triflex_exit(void) -+{ -+ pci_unregister_driver(&triflex_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for Compaq Triflex"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, triflex); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(triflex_init); -+module_exit(triflex_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pata_via.c linux-2.6.16-rc6/drivers/scsi/pata_via.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pata_via.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc6/drivers/scsi/pata_via.c 2006-03-10 16:27:29.000000000 +0000 -@@ -0,0 +1,563 @@ -+/* -+ * pata_via.c - VIA PATA for new ATA layer -+ * (C) 2005 Red Hat Inc -+ * Alan Cox <alan@redhat.com> -+ * -+ * Documentation -+ * Most chipset documentation available under NDA only -+ * -+ * VIA version guide -+ * VIA VT82C561 - early design, uses ata_generic currently -+ * VIA VT82C576 - MWDMA, 33Mhz -+ * VIA VT82C586 - MWDMA, 33Mhz -+ * VIA VT82C586a - Added UDMA to 33Mhz -+ * VIA VT82C586b - UDMA33 -+ * VIA VT82C596a - Nonfunctional UDMA66 -+ * VIA VT82C596b - Working UDMA66 -+ * VIA VT82C686 - Nonfunctional UDMA66 -+ * VIA VT82C686a - Working UDMA66 -+ * VIA VT82C686b - Updated to UDMA100 -+ * VIA VT8231 - UDMA100 -+ * VIA VT8233 - UDMA100 -+ * VIA VT8233a - UDMA133 -+ * VIA VT8233c - UDMA100 -+ * VIA VT8235 - UDMA133 -+ * VIA VT8237 - UDMA133 -+ * -+ * Most registers remain compatible across chips. Others start reserved -+ * and acquire sensible semantics if set to 1 (eg cable detect). A few -+ * exceptions exist, notably around the FIFO settings. -+ * -+ * One additional quirk of the VIA design is that like ALi they use few -+ * PCI IDs for a lot of chips. -+ * -+ * Based heavily on: -+ * -+ * Version 3.38 -+ * -+ * VIA IDE driver for Linux. Supported southbridges: -+ * -+ * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, -+ * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, -+ * vt8235, vt8237 -+ * -+ * Copyright (c) 2000-2002 Vojtech Pavlik -+ * -+ * Based on the work of: -+ * Michel Aubry -+ * Jeff Garzik -+ * Andre Hedrick -+ -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/init.h> -+#include <linux/blkdev.h> -+#include <linux/delay.h> -+#include <scsi/scsi_host.h> -+#include <linux/libata.h> -+ -+#define DRV_NAME "pata_via" -+#define DRV_VERSION "0.1.6" -+ -+/* -+ * The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx -+ * driver. -+ */ -+ -+enum { -+ VIA_UDMA = 0x007, -+ VIA_UDMA_NONE = 0x000, -+ VIA_UDMA_33 = 0x001, -+ VIA_UDMA_66 = 0x002, -+ VIA_UDMA_100 = 0x003, -+ VIA_UDMA_133 = 0x004, -+ VIA_BAD_PREQ = 0x010, /* Crashes if PREQ# till DDACK# set */ -+ VIA_BAD_CLK66 = 0x020, /* 66 MHz clock doesn't work correctly */ -+ VIA_SET_FIFO = 0x040, /* Needs to have FIFO split set */ -+ VIA_NO_UNMASK = 0x080, /* Doesn't work with IRQ unmasking on */ -+ VIA_BAD_ID = 0x100, /* Has wrong vendor ID (0x1107) */ -+ VIA_BAD_AST = 0x200, /* Don't touch Address Setup Timing */ -+ VIA_NO_ENABLES = 0x400, /* Has no enablebits */ -+}; -+ -+/* -+ * VIA SouthBridge chips. -+ */ -+ -+static const struct via_isa_bridge { -+ const char *name; -+ u16 id; -+ u8 rev_min; -+ u8 rev_max; -+ u16 flags; -+} via_isa_bridges[] = { -+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES}, -+ { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, -+ { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, -+ { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, -+ { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, -+ { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, -+ { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, -+ { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, -+ { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, -+ { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, -+ { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 }, -+ { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, -+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO }, -+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, -+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, -+ { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO }, -+ { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO }, -+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK }, -+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID }, -+ { NULL } -+}; -+ -+/** -+ * via_cable_detect - cable detection -+ * @ap: ATA port -+ * -+ * Perform cable detection. Actually for the VIA case the BIOS -+ * already did this for us. We read the values provided by the -+ * BIOS. If you are using an 8235 in a non-PC configuration you -+ * may need to update this code. -+ * -+ * Hotplug also impacts on this. -+ */ -+ -+static int via_cable_detect(struct ata_port *ap) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ u32 ata66; -+ -+ pci_read_config_dword(pdev, 0x50, &ata66); -+ /* Check both the drive cable reporting bits, we might not have -+ two drives */ -+ if (ata66 & (0x1010 << (16 * ap->hard_port_no))) -+ return ATA_CBL_PATA80; -+ else -+ return ATA_CBL_PATA40; -+} -+ -+/** -+ * via_phy_reset - reset for eary chip -+ * @ap: ATA port -+ * -+ * Handle the reset callback for the later chips with cable detect -+ */ -+ -+static void via_phy_reset(struct ata_port *ap) -+{ -+ const struct via_isa_bridge *config = ap->host_set->private_data; -+ -+ if (!(config->flags & VIA_NO_ENABLES)) { -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ static const struct pci_bits via_enable_bits[] = { -+ { 0x40, 1, 0x02, 0x02 }, -+ { 0x40, 1, 0x01, 0x01 } -+ }; -+ -+ if (!pci_test_config_bits(pdev, &via_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ } -+ -+ if ((config->flags & VIA_UDMA) >= VIA_UDMA_66) -+ ap->cbl = via_cable_detect(ap); -+ else -+ ap->cbl = ATA_CBL_PATA40; -+ -+ ata_bus_reset(ap); -+ ata_port_probe(ap); -+} -+ -+/** -+ * via_do_set_mode - set initial PIO mode data -+ * @ap: ATA interface -+ * @adev: ATA device -+ * @mode: ATA mode being programmed -+ * @tdiv: Clocks per PCI clock -+ * @set_ast: Set to program address setup -+ * @udma_type: UDMA mode/format of registers -+ * -+ * Program the VIA registers for DMA and PIO modes. Uses the ata timing -+ * support in order to compute modes. -+ * -+ * FIXME: Hotplug will require we serialize multiple mode changes -+ * on the two channels. -+ */ -+ -+static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mode, int tdiv, int set_ast, int udma_type) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); -+ struct ata_device *peer = ata_dev_pair(ap, adev); -+ struct ata_timing t, p; -+ static int via_clock = 33333; /* Bus clock in kHZ - ought to be tunable one day */ -+ unsigned long T = 1000000000 / via_clock; -+ unsigned long UT = T/tdiv; -+ int ut; -+ int offset = 3 - (2*ap->hard_port_no) - adev->devno; -+ -+ -+ /* Calculate the timing values we require */ -+ ata_timing_compute(adev, adev->pio_mode, &t, T, UT); -+ -+ /* We share 8bit timing so we must merge the constraints */ -+ if (peer) { -+ if (peer->pio_mode) { -+ ata_timing_compute(peer, peer->pio_mode, &p, T, UT); -+ ata_timing_merge(&p, &t, &t, ATA_TIMING_8BIT); -+ } -+ } -+ -+ /* Address setup is programmable but breaks on UDMA133 setups */ -+ if (set_ast) { -+ u8 setup; /* 2 bits per drive */ -+ int shift = 2 * offset; -+ -+ pci_read_config_byte(pdev, 0x4C, &setup); -+ setup &= ~(3 << shift); -+ setup |= FIT(t.setup, 1, 4) << shift; /* 1,4 or 1,4 - 1 FIXME */ -+ pci_write_config_byte(pdev, 0x4C, setup); -+ } -+ -+ printk(KERN_DEBUG "via_do_set_mode: Mode=%d ast broken=%c udma=%d mul=%d\n", -+ mode, "YN"[set_ast], udma_type, tdiv); -+ printk(KERN_DEBUG "t.act8b = %d, t.rec8b = %d, t.active = %d, t.recover = %d\n", -+ t.act8b, t.rec8b, t.active, t.recover); -+ printk(KERN_DEBUG "FIT t.act8b = %d, t.rec8b = %d, t.active = %d, t.recover = %d\n", -+ FIT(t.act8b,1,16) -1, -+ FIT(t.rec8b,1,16) -1, -+ FIT(t.active,1,16) -1, -+ FIT(t.recover,1,16) -1); -+ -+ /* Load the PIO mode bits */ -+ pci_write_config_byte(pdev, 0x4F - ap->hard_port_no, -+ ((FIT(t.act8b, 1, 16) - 1) << 4) | (FIT(t.rec8b, 1, 16) - 1)); -+ pci_write_config_byte(pdev, 0x48 + offset, -+ ((FIT(t.active, 1, 16) - 1) << 4) | (FIT(t.recover, 1, 16) - 1)); -+ -+ /* Load the UDMA bits according to type */ -+ switch(udma_type) { -+ default: -+ /* BUG() ? */ -+ /* fall through */ -+ case 33: -+ ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 5) - 2)) : 0x03; -+ break; -+ case 66: -+ ut = t.udma ? (0xe8 | (FIT(t.udma, 2, 9) - 2)) : 0x0f; -+ break; -+ case 100: -+ ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; -+ break; -+ case 133: -+ ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07; -+ break; -+ } -+ /* Set UDMA unless device is not UDMA capable */ -+ if (udma_type) -+ pci_write_config_byte(pdev, 0x50 + offset, ut); -+} -+ -+static void via_set_piomode(struct ata_port *ap, struct ata_device *adev) -+{ -+ const struct via_isa_bridge *config = ap->host_set->private_data; -+ int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; -+ int mode = config->flags & VIA_UDMA; -+ static u8 tclock[5] = { 1, 1, 2, 3, 4 }; -+ static u8 udma[5] = { 0, 33, 66, 100, 133 }; -+ -+ via_do_set_mode(ap, adev, adev->pio_mode, tclock[mode], set_ast, udma[mode]); -+} -+ -+static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) -+{ -+ const struct via_isa_bridge *config = ap->host_set->private_data; -+ int set_ast = (config->flags & VIA_BAD_AST) ? 0 : 1; -+ int mode = config->flags & VIA_UDMA; -+ static u8 tclock[5] = { 1, 1, 2, 3, 4 }; -+ static u8 udma[5] = { 0, 33, 66, 100, 133 }; -+ -+ via_do_set_mode(ap, adev, adev->dma_mode, tclock[mode], set_ast, udma[mode]); -+} -+ -+static struct scsi_host_template via_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .ioctl = ata_scsi_ioctl, -+ .queuecommand = ata_scsi_queuecmd, -+ .eh_strategy_handler = ata_scsi_error, -+ .can_queue = ATA_DEF_QUEUE, -+ .this_id = ATA_SHT_THIS_ID, -+ .sg_tablesize = LIBATA_MAX_PRD, -+ .max_sectors = ATA_MAX_SECTORS, -+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations via_port_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = via_set_piomode, -+ .set_dmamode = via_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = via_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static struct ata_port_operations via_port_ops_noirq = { -+ .port_disable = ata_port_disable, -+ .set_piomode = via_set_piomode, -+ .set_dmamode = via_set_dmamode, -+ .tf_load = ata_tf_load, -+ .tf_read = ata_tf_read, -+ .check_status = ata_check_status, -+ .exec_command = ata_exec_command, -+ .dev_select = ata_std_dev_select, -+ -+ .phy_reset = via_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer_noirq, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+/** -+ * via_init_one - discovery callback -+ * @pdev: PCI device ID -+ * @id: PCI table info -+ * -+ * A VIA IDE interface has been discovered. Figure out what revision -+ * and perform configuration work before handing it to the ATA layer -+ */ -+ -+static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ /* Early VIA without UDMA support */ -+ static struct ata_port_info via_mwdma_info = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &via_port_ops -+ }; -+ /* Ditto with IRQ masking required */ -+ static struct ata_port_info via_mwdma_info_borked = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_IRQ_MASK, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .port_ops = &via_port_ops_noirq, -+ }; -+ /* VIA UDMA 33 devices (and borked 66) */ -+ static struct ata_port_info via_udma33_info = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7, -+ .port_ops = &via_port_ops -+ }; -+ /* VIA UDMA 66 devices */ -+ static struct ata_port_info via_udma66_info = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x1f, -+ .port_ops = &via_port_ops -+ }; -+ /* VIA UDMA 100 devices */ -+ static struct ata_port_info via_udma100_info = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &via_port_ops -+ }; -+ /* UDMA133 with bad AST (All current 133) */ -+ static struct ata_port_info via_udma133_info = { -+ .sht = &via_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x7f, /* FIXME: should check north bridge */ -+ .port_ops = &via_port_ops -+ }; -+ struct ata_port_info *port_info[2], *type; -+ struct pci_dev *isa = NULL; -+ const struct via_isa_bridge *config; -+ static int printed_version; -+ u8 t; -+ u8 enable; -+ u32 timing; -+ -+ if (!printed_version++) -+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); -+ -+ /* To find out how the IDE will behave and what features we -+ actually have to look at the bridge not the IDE controller */ -+ for (config = via_isa_bridges; config->id; config++) -+ if ((isa = pci_get_device(PCI_VENDOR_ID_VIA + -+ !!(config->flags & VIA_BAD_ID), -+ config->id, NULL))) { -+ -+ pci_read_config_byte(isa, PCI_REVISION_ID, &t); -+ if (t >= config->rev_min && -+ t <= config->rev_max) -+ break; -+ pci_dev_put(isa); -+ } -+ -+ if (!config->id) { -+ printk(KERN_WARNING "via: Unknown VIA SouthBridge, disabling.\n"); -+ return -ENODEV; -+ } -+ -+ /* 0x40 low bits indicate enabled channels */ -+ pci_read_config_byte(pdev, 0x40 , &enable); -+ enable &= 3; -+ if (enable == 0) { -+ pci_dev_put(isa); -+ return -ENODEV; -+ } -+ -+ /* Initialise the FIFO for the enabled channels. */ -+ if (config->flags & VIA_SET_FIFO) { -+ u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20}; -+ u8 fifo; -+ -+ pci_read_config_byte(pdev, 0x43, &fifo); -+ -+ /* Clear PREQ# until DDACK# for errata */ -+ if (config->flags & VIA_BAD_PREQ) -+ fifo &= 0x7F; -+ else -+ fifo &= 0x9f; -+ /* Turn on FIFO for enabled channels */ -+ fifo |= fifo_setting[enable]; -+ pci_write_config_byte(pdev, 0x43, fifo); -+ } -+ /* Clock set up */ -+ switch(config->flags & VIA_UDMA) { -+ case VIA_UDMA_NONE: -+ if (config->flags & VIA_NO_UNMASK) -+ type = &via_mwdma_info_borked; -+ else -+ type = &via_mwdma_info; -+ break; -+ case VIA_UDMA_33: -+ type = &via_udma33_info; -+ break; -+ case VIA_UDMA_66: -+ type = &via_udma66_info; -+ /* The 66 MHz devices require we enable the clock */ -+ pci_read_config_dword(pdev, 0x50, &timing); -+ timing |= 0x80008; -+ pci_write_config_dword(pdev, 0x50, timing); -+ break; -+ case VIA_UDMA_100: -+ type = &via_udma100_info; -+ break; -+ case VIA_UDMA_133: -+ type = &via_udma133_info; -+ break; -+ default: -+ type = NULL; -+ BUG(); -+ break; -+ } -+ -+ if (config->flags & VIA_BAD_CLK66) { -+ /* Disable the 66MHz clock on problem devices */ -+ pci_read_config_dword(pdev, 0x50, &timing); -+ timing &= ~0x80008; -+ pci_write_config_dword(pdev, 0x50, timing); -+ } -+ -+ /* We have established the device type, now fire it up */ -+ type->private_data = (void *)config; -+ -+ port_info[0] = port_info[1] = type; -+ return ata_pci_init_one(pdev, port_info, 2); -+} -+ -+static const struct pci_device_id via[] = { -+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -+ { 0, }, -+}; -+ -+static struct pci_driver via_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = via, -+ .probe = via_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init via_init(void) -+{ -+ return pci_register_driver(&via_pci_driver); -+} -+ -+ -+static void __exit via_exit(void) -+{ -+ pci_unregister_driver(&via_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for VIA PATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, via); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(via_init); -+module_exit(via_exit); -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/pdc_adma.c linux-2.6.16-rc6/drivers/scsi/pdc_adma.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/pdc_adma.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/pdc_adma.c 2006-02-23 13:15:50.000000000 +0000 -@@ -322,7 +322,7 @@ - = (pFLAGS & pEND) ? 0 : cpu_to_le32(pp->pkt_dma + i + 4); - i += 4; - -- VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", nelem, -+ VPRINTK("PRD[%u] = (0x%lX, 0x%X)\n", i/4, - (unsigned long)addr, len); - } - return i; -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_mv.c linux-2.6.16-rc6/drivers/scsi/sata_mv.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_mv.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_mv.c 2006-02-20 11:28:03.000000000 +0000 -@@ -389,6 +389,7 @@ - - .qc_prep = mv_qc_prep, - .qc_issue = mv_qc_issue, -+ .data_xfer = ata_mmio_data_xfer, - - .eng_timeout = mv_eng_timeout, - -@@ -416,6 +417,7 @@ - - .qc_prep = mv_qc_prep, - .qc_issue = mv_qc_issue, -+ .data_xfer = ata_mmio_data_xfer, - - .eng_timeout = mv_eng_timeout, - -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_nv.c linux-2.6.16-rc6/drivers/scsi/sata_nv.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_nv.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_nv.c 2006-01-21 17:08:58.000000000 +0000 -@@ -258,6 +258,7 @@ - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .eng_timeout = ata_eng_timeout, -+ .data_xfer = ata_pio_data_xfer, - .irq_handler = nv_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .scr_read = nv_scr_read, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_promise.c linux-2.6.16-rc6/drivers/scsi/sata_promise.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_promise.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_promise.c 2006-02-06 12:36:12.000000000 +0000 -@@ -130,6 +130,7 @@ - .qc_prep = pdc_qc_prep, - .qc_issue = pdc_qc_issue_prot, - .eng_timeout = pdc_eng_timeout, -+ .data_xfer = ata_mmio_data_xfer, - .irq_handler = pdc_interrupt, - .irq_clear = pdc_irq_clear, - -@@ -152,6 +153,7 @@ - - .qc_prep = pdc_qc_prep, - .qc_issue = pdc_qc_issue_prot, -+ .data_xfer = ata_mmio_data_xfer, - .eng_timeout = pdc_eng_timeout, - .irq_handler = pdc_interrupt, - .irq_clear = pdc_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_qstor.c linux-2.6.16-rc6/drivers/scsi/sata_qstor.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_qstor.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_qstor.c 2006-02-27 14:35:16.000000000 +0000 -@@ -158,6 +158,7 @@ - .phy_reset = qs_phy_reset, - .qc_prep = qs_qc_prep, - .qc_issue = qs_qc_issue, -+ .data_xfer = ata_mmio_data_xfer, - .eng_timeout = qs_eng_timeout, - .irq_handler = qs_intr, - .irq_clear = qs_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sil24.c linux-2.6.16-rc6/drivers/scsi/sata_sil24.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sil24.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_sil24.c 2006-01-21 17:10:52.000000000 +0000 -@@ -309,6 +309,7 @@ - - .qc_prep = sil24_qc_prep, - .qc_issue = sil24_qc_issue, -+ .data_xfer = ata_mmio_data_xfer, - - .eng_timeout = sil24_eng_timeout, - -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sil.c linux-2.6.16-rc6/drivers/scsi/sata_sil.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sil.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_sil.c 2006-03-13 14:03:24.000000000 +0000 -@@ -167,6 +167,7 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_mmio_data_xfer, - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sis.c linux-2.6.16-rc6/drivers/scsi/sata_sis.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sis.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_sis.c 2006-01-21 17:11:23.000000000 +0000 -@@ -115,6 +115,7 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_svw.c linux-2.6.16-rc6/drivers/scsi/sata_svw.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_svw.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_svw.c 2006-02-06 12:30:23.000000000 +0000 -@@ -320,6 +320,7 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_mmio_data_xfer, - .eng_timeout = ata_eng_timeout, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sx4.c linux-2.6.16-rc6/drivers/scsi/sata_sx4.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_sx4.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_sx4.c 2006-01-21 17:12:01.000000000 +0000 -@@ -206,6 +206,7 @@ - .phy_reset = pdc_20621_phy_reset, - .qc_prep = pdc20621_qc_prep, - .qc_issue = pdc20621_qc_issue_prot, -+ .data_xfer = ata_mmio_data_xfer, - .eng_timeout = pdc_eng_timeout, - .irq_handler = pdc20621_interrupt, - .irq_clear = pdc20621_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_uli.c linux-2.6.16-rc6/drivers/scsi/sata_uli.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_uli.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_uli.c 2006-01-21 17:12:24.000000000 +0000 -@@ -106,6 +106,7 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_via.c linux-2.6.16-rc6/drivers/scsi/sata_via.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_via.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_via.c 2006-01-21 17:12:51.000000000 +0000 -@@ -126,6 +126,7 @@ - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/sata_vsc.c linux-2.6.16-rc6/drivers/scsi/sata_vsc.c ---- linux.vanilla-2.6.16-rc6/drivers/scsi/sata_vsc.c 2006-03-13 14:00:14.000000000 +0000 -+++ linux-2.6.16-rc6/drivers/scsi/sata_vsc.c 2006-02-20 11:28:11.000000000 +0000 -@@ -280,6 +280,7 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ .data_xfer = ata_pio_data_xfer, - .eng_timeout = ata_eng_timeout, - .irq_handler = vsc_sata_interrupt, - .irq_clear = ata_bmdma_irq_clear, -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/include/linux/ata.h linux-2.6.16-rc6/include/linux/ata.h ---- linux.vanilla-2.6.16-rc6/include/linux/ata.h 2006-03-13 14:00:15.000000000 +0000 -+++ linux-2.6.16-rc6/include/linux/ata.h 2006-02-15 14:39:41.000000000 +0000 -@@ -134,6 +134,8 @@ - ATA_CMD_PIO_READ_EXT = 0x24, - ATA_CMD_PIO_WRITE = 0x30, - ATA_CMD_PIO_WRITE_EXT = 0x34, -+ ATA_CMD_READ_NATIVE_MAX = 0xF8, -+ ATA_CMD_READ_NATIVE_MAX_EXT = 0x27, - ATA_CMD_READ_MULTI = 0xC4, - ATA_CMD_READ_MULTI_EXT = 0x29, - ATA_CMD_WRITE_MULTI = 0xC5, -@@ -247,18 +249,22 @@ - }; - - #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) -+#define ata_id_is_cfa(id) ((id)[0] == 0x848A) - #define ata_id_is_sata(id) ((id)[93] == 0) - #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) - #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) -+#define ata_id_hpa_enabled(id) ((id)[85] & (1 << 10)) - #define ata_id_has_fua(id) ((id)[84] & (1 << 6)) - #define ata_id_has_flush(id) ((id)[83] & (1 << 12)) - #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) - #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) -+#define ata_id_has_hpa(id) ((id)[82] & (1 << 10)) - #define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) - #define ata_id_has_pm(id) ((id)[82] & (1 << 3)) - #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) - #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) - #define ata_id_removeable(id) ((id)[0] & (1 << 7)) -+#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0)) - #define ata_id_u32(id,n) \ - (((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)])) - #define ata_id_u64(id,n) \ -diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/include/linux/libata.h linux-2.6.16-rc6/include/linux/libata.h ---- linux.vanilla-2.6.16-rc6/include/linux/libata.h 2006-03-13 14:00:15.000000000 +0000 -+++ linux-2.6.16-rc6/include/linux/libata.h 2006-03-10 16:48:12.000000000 +0000 -@@ -39,9 +39,9 @@ - */ - #undef ATA_DEBUG /* debugging output */ - #undef ATA_VERBOSE_DEBUG /* yet more debugging output */ --#undef ATA_IRQ_TRAP /* define to ack screaming irqs */ -+#define ATA_IRQ_TRAP /* define to ack screaming irqs */ - #undef ATA_NDEBUG /* define to disable quick runtime checks */ --#undef ATA_ENABLE_PATA /* define to enable PATA support in some -+#define ATA_ENABLE_PATA /* define to enable PATA support in some - * low-level drivers */ - #undef ATAPI_ENABLE_DMADIR /* enables ATAPI DMADIR bridge support */ - -@@ -101,6 +101,7 @@ - ATA_DFLAG_PIO = (1 << 1), /* device currently in PIO mode */ - ATA_DFLAG_LOCK_SECTORS = (1 << 2), /* don't adjust max_sectors */ - ATA_DFLAG_LBA = (1 << 3), /* device supports LBA */ -+ ATA_DFLAG_HPA = (1 << 4), /* device has an HPA */ - - ATA_DEV_UNKNOWN = 0, /* unknown device */ - ATA_DEV_ATA = 1, /* ATA device */ -@@ -133,6 +134,8 @@ - ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ - ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ - ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, -+ -+ ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ - - /* various lengths of time */ - ATA_TMOUT_EDD = 5 * HZ, /* heuristic */ -@@ -197,6 +200,7 @@ - - /* forward declarations */ - struct scsi_device; -+struct ata_host_set; - struct ata_port_operations; - struct ata_port; - struct ata_queued_cmd; -@@ -237,8 +241,10 @@ - unsigned long irq; - unsigned int irq_flags; - unsigned long host_flags; -+ unsigned long host_set_flags; - void __iomem *mmio_base; - void *private_data; -+ struct ata_host_set *host_set; /* Return not input value */ - }; - - struct ata_host_set { -@@ -250,6 +256,9 @@ - void *private_data; - const struct ata_port_operations *ops; - struct ata_port * ports[0]; -+ unsigned long host_set_flags; -+ int simplex_claimed; /* Keep seperate in case we -+ ever need to do this locked */ - }; - - struct ata_queued_cmd { -@@ -369,6 +378,7 @@ - - void (*set_piomode) (struct ata_port *, struct ata_device *); - void (*set_dmamode) (struct ata_port *, struct ata_device *); -+ unsigned int (*mode_filter) (const struct ata_port *, struct ata_device *, unsigned int, int); - - void (*tf_load) (struct ata_port *ap, const struct ata_taskfile *tf); - void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); -@@ -379,12 +389,15 @@ - void (*dev_select)(struct ata_port *ap, unsigned int device); - - void (*phy_reset) (struct ata_port *ap); -+ void (*set_mode) (struct ata_port *ap); - void (*post_set_mode) (struct ata_port *ap); - - int (*check_atapi_dma) (struct ata_queued_cmd *qc); - - void (*bmdma_setup) (struct ata_queued_cmd *qc); - void (*bmdma_start) (struct ata_queued_cmd *qc); -+ -+ void (*data_xfer) (struct ata_port *, struct ata_device *, unsigned char *, unsigned int, int); - - void (*qc_prep) (struct ata_queued_cmd *qc); - int (*qc_issue) (struct ata_queued_cmd *qc); -@@ -443,8 +456,9 @@ - extern void ata_pci_remove_one (struct pci_dev *pdev); - extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); - extern int ata_pci_device_resume(struct pci_dev *pdev); -+extern int ata_pci_clear_simplex(struct pci_dev *pdev); - #endif /* CONFIG_PCI */ --extern int ata_device_add(const struct ata_probe_ent *ent); -+extern int ata_device_add(struct ata_probe_ent *ent); - extern void ata_host_set_remove(struct ata_host_set *host_set); - extern int ata_scsi_detect(struct scsi_host_template *sht); - extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); -@@ -491,6 +505,15 @@ - extern void ata_bmdma_irq_clear(struct ata_port *ap); - extern void ata_qc_complete(struct ata_queued_cmd *qc); - extern void ata_eng_timeout(struct ata_port *ap); -+extern void ata_mmio_data_xfer(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, -+ unsigned int buflen, int write_data); -+extern void ata_pio_data_xfer(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, -+ unsigned int buflen, int write_data); -+extern void ata_mmio_data_xfer_noirq(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, -+ unsigned int buflen, int do_write); -+extern void ata_pio_data_xfer_noirq(struct ata_port *ap, struct ata_device *adev, unsigned char *buf, -+ unsigned int buflen, int do_write); -+ - extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, - void (*done)(struct scsi_cmnd *)); -@@ -498,6 +521,8 @@ - struct block_device *bdev, - sector_t capacity, int geom[]); - extern int ata_scsi_slave_config(struct scsi_device *sdev); -+extern struct ata_device *ata_dev_pair(struct ata_port *ap, -+ struct ata_device *adev); - - /* - * Timing helpers |