diff -Naur linux-2.6.0-test10/Makefile linux-2.6.0-test10-obs266/Makefile
--- linux-2.6.0-test10/Makefile	Mon Nov 24 10:32:30 2003
+++ linux-2.6.0-test10-obs266/Makefile	Wed Nov 26 16:35:21 2003
@@ -125,9 +125,7 @@
 # then ARCH is assigned, getting whatever value it gets normally, and 
 # SUBARCH is subsequently ignored.
 
-SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-				  -e s/arm.*/arm/ -e s/sa110/arm/ \
-				  -e s/s390x/s390/ -e s/parisc64/parisc/ )
+SUBARCH := ppc
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
@@ -149,7 +147,7 @@
 # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
 
 ARCH		?= $(SUBARCH)
-CROSS_COMPILE	?=
+CROSS_COMPILE	?= ppc_405-
 
 # Architecture as present in compile.h
 UTS_MACHINE := $(ARCH)
diff -Naur linux-2.6.0-test10/arch/ppc/Kconfig linux-2.6.0-test10-obs266/arch/ppc/Kconfig
--- linux-2.6.0-test10/arch/ppc/Kconfig	Mon Nov 24 10:33:23 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/Kconfig	Wed Nov 26 23:54:42 2003
@@ -640,7 +640,7 @@
 
 config SERIAL_CONSOLE
 	bool
-	depends on 8xx || 8260
+	depends on 8xx || 8260 || OPENBLOCKS266
 	default y
 
 config SERIAL_CONSOLE_BAUD
diff -Naur linux-2.6.0-test10/arch/ppc/boot/simple/embed_config.c linux-2.6.0-test10-obs266/arch/ppc/boot/simple/embed_config.c
--- linux-2.6.0-test10/arch/ppc/boot/simple/embed_config.c	Mon Nov 24 10:31:12 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/boot/simple/embed_config.c	Wed Nov 26 22:55:27 2003
@@ -732,7 +732,7 @@
 	 */
 	mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);     /* 1st reset MAL */
 	while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */	
-	out_be32(EMAC0_BASE,0x20000000);        /* then reset EMAC */
+	out_be32((u32*)EMAC0_BASE, 0x20000000);        /* then reset EMAC */
 #endif
 
 	bd = &bdinfo;
diff -Naur linux-2.6.0-test10/arch/ppc/boot/simple/misc-embedded.c linux-2.6.0-test10-obs266/arch/ppc/boot/simple/misc-embedded.c
--- linux-2.6.0-test10/arch/ppc/boot/simple/misc-embedded.c	Mon Nov 24 10:31:14 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/boot/simple/misc-embedded.c	Thu Nov 27 04:36:44 2003
@@ -14,6 +14,7 @@
 #include <asm/mmu.h>
 #include <asm/page.h>
 #include <asm/residual.h>
+#include <asm/reg.h>
 #if defined(CONFIG_4xx)
 #include <asm/ibm4xx.h>
 #elif defined(CONFIG_8xx)
@@ -58,6 +59,51 @@
 char ramroot_string[] = "root=/dev/ram";
 char netroot_string[] = "root=/dev/nfs rw ip=on";
 
+#ifdef CONFIG_OPENBLOCKS266
+char eeprom_root_string[30] = { 0 };
+static int get_root_parameter(bd_t *b, char *str)
+{
+	int i;
+	char *p = str;
+
+	if (b == NULL) return 1;	/* something error */
+
+#if 0	/* for debug */
+	puts("\n[");
+	for (i = 0; i < sizeof(b->bi_r_version); i++) {
+		puts(" ");
+		puthex(b->bi_r_version[i]);
+	}
+	puts("]\n");
+#endif
+
+	for (i = 0; i < sizeof(b->bi_r_version); i++) {
+		if (b->bi_r_version[i] == '\0') goto found;
+	}
+	return 2;	/* no null termination */
+found:
+	*p = '\0';
+	for (i += 1; i < sizeof(b->bi_r_version); i++) {
+		*p++ = b->bi_r_version[i];
+		if (b->bi_r_version[i] == '\0') {
+			if (p == str) return 3;	/* Maybe old ROM Monitor... */
+			return 0;	/* OK */
+		}
+	}
+	return 4;	/* too long */
+}
+
+static int is_pushsw(bd_t *b)
+{
+#define PUSHSW_INT	26
+	if (mfdcr(DCRN_UIC_SR(UIC0)) & (1 << (31 - PUSHSW_INT))) {
+		b->bi_s_version[0] = '\0';
+		return 1;
+	}
+	return 0;
+}
+#endif
+
 /* Serial port to use. */
 unsigned long com_port;
 
@@ -179,9 +225,22 @@
 	else
 		memcpy (cmd_line, netroot_string, sizeof(netroot_string));
 #endif
+#ifdef CONFIG_OPENBLOCKS266
+	if (!is_pushsw(hold_residual) && get_root_parameter(bp, eeprom_root_string) == 0) {
+//		int len = strlen(eeprom_root_string);
+//		memcpy (cmd_line, "root=/dev/", 10);
+//		memcpy (cmd_line + 10, eeprom_root_string, len + 1);
+		memcpy (cmd_line, "root=/dev/hdg1", 14); /* or /dev/ram0 */
+	}
+#endif
 	while ( *cp )
 		putc(*cp++);
-	while (timer++ < 5*1000) {
+#ifdef CONFIG_OPENBLOCKS266
+#define BOOT_WAIT_TIME (400)   /* real 2sec */
+#else
+#define BOOT_WAIT_TIME (5*1000)
+#endif
+	while (timer++ < BOOT_WAIT_TIME) {
 		if (tstc()) {
 			while ((ch = getc()) != '\n' && ch != '\r') {
 				if (ch == '\b' || ch == '\177') {
@@ -261,7 +320,7 @@
 		rec = (struct bi_record *)((unsigned long)rec + rec->size);
 	}
 	puts("Now booting the kernel\n");
-	serial_close(com_port);
+	//serial_close(com_port);
 
 	return (unsigned long)hold_residual;
 }
diff -Naur linux-2.6.0-test10/arch/ppc/platforms/4xx/Kconfig linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/Kconfig
--- linux-2.6.0-test10/arch/ppc/platforms/4xx/Kconfig	Mon Nov 24 10:31:12 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/Kconfig	Wed Nov 26 18:58:35 2003
@@ -9,7 +9,7 @@
 choice
 	prompt "Machine Type"
 	depends on 40x
-	default WALNUT
+	default OPENBLOCKS266
 
 config ASH
 	bool "Ash"
@@ -56,6 +56,9 @@
 	help
 	  Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board.
 
+config OPENBLOCKS266
+	bool "OpenBlockS266"
+
 endchoice
 
 choice
@@ -133,7 +136,7 @@
 
 config IBM_OCP
 	bool
-	depends on ASH || BEECH || CEDAR || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	depends on ASH || BEECH || CEDAR || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT || OPENBLOCKS266
 	default y
 
 config IBM_EMAC4
@@ -148,7 +151,7 @@
 
 config BIOS_FIXUP
 	bool
-	depends on CEDAR || EP405 || SYCAMORE || WALNUT
+	depends on CEDAR || EP405 || SYCAMORE || WALNUT || OPENBLOCKS266
 	default y
 
 config 403GCX
@@ -158,7 +161,7 @@
 
 config 405GP
 	bool
-	depends on CPCI405 || EP405 || WALNUT
+	depends on CPCI405 || EP405 || WALNUT || OPENBLOCKS266
 	default y
 
 config 405GPR
@@ -181,7 +184,7 @@
 
 config IBM_OPENBIOS
 	bool
-	depends on ASH || BEECH || CEDAR || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+	depends on ASH || BEECH || CEDAR || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT || OPENBLOCKS266
 	default y
 
 config 405_DMA
diff -Naur linux-2.6.0-test10/arch/ppc/platforms/4xx/Makefile linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/Makefile
--- linux-2.6.0-test10/arch/ppc/platforms/4xx/Makefile	Mon Nov 24 10:32:53 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/Makefile	Wed Nov 26 20:00:58 2003
@@ -14,6 +14,7 @@
 obj-$(CONFIG_REDWOOD_6)		+= redwood6.o
 obj-$(CONFIG_SYCAMORE)		+= sycamore.o
 obj-$(CONFIG_WALNUT)		+= walnut.o
+obj-$(CONFIG_OPENBLOCKS266)	+= openblocks266.o
 
 obj-$(CONFIG_NP405L)		+= ibmnp405l.o
 obj-$(CONFIG_405GP)		+= ibm405gp.o
diff -Naur linux-2.6.0-test10/arch/ppc/platforms/4xx/openblocks266.c linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/openblocks266.c
--- linux-2.6.0-test10/arch/ppc/platforms/4xx/openblocks266.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/openblocks266.c	Wed Nov 26 22:04:12 2003
@@ -0,0 +1,276 @@
+/*
+ *
+ *    Copyright (c) 2003 AXE,Inc.
+ *    openblocks266.c: Based on walnut.c
+ *
+ *    Copyrigh t(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Copyright 2000-2002 MontaVista Software Inc.
+ *      Completed implementation.
+ *      Author: MontaVista Software, Inc.  <source@mvista.com>
+ *
+ *    Module name: walnut.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      IBM PowerPC 4xx based boards. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
+ *
+ *      History: 11/09/2001 - armin
+ *      added board_init to add in additional instuctions needed during platfrom_init
+ *
+ *      01/22/2002 - Armin
+ *      converted pci to ocp
+ *
+ *
+ * Please read the COPYING file for all license details.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blkdev.h>
+#include <linux/pci.h>
+#include <linux/rtc.h>
+
+#include <asm/system.h>
+#include <asm/pci-bridge.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/todc.h>
+#include <asm/delay.h>
+#include <asm/ibm_ocp_pci.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void *kb_cs;
+void *kb_data;
+void *openblocks266_rtc_base;
+
+/* Some IRQs unique to OpenBlockS266.
+ * Used by the generic 405 PCI setup functions in ppc4xx_pci.c
+ */
+int __init
+ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *      A       B       C       D
+	     */
+	{
+		{28, 28, 28, 28},	/* IDSEL 1 - PCI slot 1 */
+		{29, 29, 29, 29},	/* IDSEL 2 - PCI slot 2 */
+		{30, 30, 30, 30},	/* IDSEL 3 - PCI slot 3 */
+		{31, 31, 31, 31},	/* IDSEL 4 - PCI slot 4 */
+	};
+
+	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP;
+};
+
+void __init
+obs266_setup_arch(void)
+{
+#define OPENBLOCKS266_PS2_BASE	0xF0100000
+#define OPENBLOCKS266_FPGA_BASE	0xF0300000
+
+	void *fpga_brdc;
+	void *fpga_enable;
+	void *fpga_polarity;
+	void *fpga_status;
+	void *fpga_trigger;
+
+	ppc4xx_setup_arch();
+	
+	kb_data = ioremap(OPENBLOCKS266_PS2_BASE, 8);
+	if (!kb_data) {
+		printk(KERN_CRIT
+		       "openblocks266_setup_arch() kb_data ioremap failed\n");
+		return;
+	}
+
+	kb_cs = kb_data + 1;
+
+	fpga_status = ioremap(OPENBLOCKS266_FPGA_BASE, 8);
+	if (!fpga_status) {
+		printk(KERN_CRIT
+		       "openblocks266_setup_arch() fpga_status ioremap failed\n");
+		return;
+	}
+
+
+	fpga_enable = fpga_status + 1;
+	fpga_polarity = fpga_status + 2;
+	fpga_trigger = fpga_status + 3;
+	fpga_brdc = fpga_status + 4;
+
+	/* Identify the system */
+	printk("OpenBlockS port\n");
+	/* printk("IBM Walnut port (C) 2000-2002 MontaVista Software, Inc. (source@mvista.com)\n"); */
+}
+
+static void obs_reset_pci_bus(struct pci_controller *hose)
+{
+	u16 brdgopt2;
+
+	/* obs_dump_pci_conf(hose, 0, PCI_DEVFN(0,0)); */
+	if( early_read_config_word(hose, 0, PCI_DEVFN(0,0), 0x60, &brdgopt2) ){
+		printk("OpenBlockS: read error PCI:(bus:%d,dev:%d,fn:%d,addr:%02x)\n", 0,0,0, 0x60);
+		return;
+	}
+	if( early_write_config_word(hose, 0, PCI_DEVFN(0,0), 0x60, brdgopt2 | 0x1000) ){
+		printk("OpenBlockS: read error PCI:(bus:%d,dev:%d,fn:%d,addr:%02x)\n", 0,0,0, 0x60);
+		return;
+	}
+
+	udelay(1000); udelay(1000); udelay(1000); udelay(1000);
+
+	if( early_write_config_word(hose, 0, PCI_DEVFN(0,0), 0x60, (brdgopt2 & ~0x1000) & 0xffff) ){
+		printk("OpenBlockS: read error PCI:(bus:%d,dev:%d,fn:%d,addr:%02x)\n", 0,0,0, 0x60);
+
+	}
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	/* Aviod a HPT371 vender ID broken problem in restart machine */
+	obs_reset_pci_bus(hose);
+
+	/* obs_hpt371_dump_pci_conf(hose); */
+	/* obs_hpt371_load_vender_id(hose);*/ /* Don't work... */
+
+#ifdef NEVER	/* OpenBlockS bios fixup is done at 405GPr ROM Monitor */
+	unsigned int bar_response, bar;
+	/*
+	 * Expected PCI mapping:
+	 *
+	 *  PLB addr             PCI memory addr
+	 *  ---------------------       ---------------------
+	 *  0000'0000 - 7fff'ffff <---  0000'0000 - 7fff'ffff
+	 *  8000'0000 - Bfff'ffff --->  8000'0000 - Bfff'ffff
+	 *
+	 *  PLB addr             PCI io addr
+	 *  ---------------------       ---------------------
+	 *  e800'0000 - e800'ffff --->  0000'0000 - 0001'0000
+	 *
+	 * The following code is simplified by assuming that the bootrom
+	 * has been well behaved in following this mapping.
+	 */
+
+#ifdef DEBUG
+	int i;
+
+	printk("ioremap PCLIO_BASE = 0x%x\n", pcip);
+	printk("PCI bridge regs before fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+
+	/* added for IBM boot rom version 1.15 bios bar changes  -AK */
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000000);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+		DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n",
+		    hose->first_busno, PCI_SLOT(hose->first_busno),
+		    PCI_FUNC(hose->first_busno), bar, bar_response);
+	}
+	/* end work arround */
+
+#ifdef DEBUG
+	printk("PCI bridge regs after fixup \n");
+	for (i = 0; i <= 3; i++) {
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila)));
+		printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha)));
+	}
+	printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms)));
+	printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la)));
+	printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms)));
+	printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la)));
+
+#endif
+#endif /* NEVER */
+}
+
+void __init
+obs266_map_io(void)
+{
+	ppc4xx_map_io();
+	io_block_mapping(OPENBLOCKS266_RTC_VADDR, OPENBLOCKS266_RTC_PADDR,
+			 OPENBLOCKS266_RTC_SIZE, _PAGE_IO);
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	ppc4xx_init(r3, r4, r5, r6, r7);
+
+	ppc_md.setup_arch = obs266_setup_arch;
+	ppc_md.setup_io_mappings = obs266_map_io;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.nvram_read_val = NULL;
+	ppc_md.nvram_write_val = NULL;
+}
diff -Naur linux-2.6.0-test10/arch/ppc/platforms/4xx/openblocks266.h linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/openblocks266.h
--- linux-2.6.0-test10/arch/ppc/platforms/4xx/openblocks266.h	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/arch/ppc/platforms/4xx/openblocks266.h	Wed Nov 26 19:10:37 2003
@@ -0,0 +1,92 @@
+/*
+ *
+ *    Copyright (c) 2003 AXE,Inc.
+ *    openblocks266.h: Based on walnut.h
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: ppc405.h
+ *
+ *    Description:
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      based boards.
+ *
+ *      This includes:
+ *
+ *         405GP "Walnut" evaluation board
+ *
+ * Please read the COPYING file for all license details.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_OPENBLOCKS266_H__
+#define __ASM_OPENBLOCKS266_H__
+
+/* We have a 405GPr core */
+#include <platforms/4xx/ibm405gpr.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Walnut" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+
+/* Some 4xx parts use a different timebase frequency from the internal clock.
+*/
+#define bi_tbfreq bi_intfreq
+
+
+/* Memory map for the OpenBlockS266.
+ * Generic 4xx plus RTC.
+ */
+
+extern void *openblocks266_rtc_base;
+#define OPENBLOCKS266_RTC_PADDR	((uint)0xf0000000)
+#define OPENBLOCKS266_RTC_VADDR	OPENBLOCKS266_RTC_PADDR
+#define OPENBLOCKS266_RTC_SIZE	((uint)8*1024)
+
+/* ps2 keyboard and mouse */
+#define KEYBOARD_IRQ		25
+#define AUX_IRQ			26
+
+#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD               (7372800/16)
+#endif
+
+#define OPENBLOCKS266_PS2_BASE	0xF0100000
+#define OPENBLOCKS266_FPGA_BASE	0xF0300000
+
+
+extern void *kb_cs;
+extern void *kb_data;
+#define kbd_read_input()	readb(kb_data)
+#define kbd_read_status()	readb(kb_cs)
+#define kbd_write_output(val)	writeb(val, kb_data)
+#define kbd_write_command(val)	writeb(val, kb_cs)
+
+#define PPC4xx_MACHINE_NAME	"OpenBlockS266"
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __ASM_OPENBLOCKS266_H__ */
+#endif /* __KERNEL__ */
diff -Naur linux-2.6.0-test10/arch/ppc/syslib/ppc4xx_pic.c linux-2.6.0-test10-obs266/arch/ppc/syslib/ppc4xx_pic.c
--- linux-2.6.0-test10/arch/ppc/syslib/ppc4xx_pic.c	Mon Nov 24 10:30:55 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/syslib/ppc4xx_pic.c	Wed Nov 26 18:02:26 2003
@@ -155,6 +155,15 @@
 #ifdef UIC_DEBUG
 	printk("ppc405_uic_enable - irq %d word %d bit 0x%x\n", irq, word, bit);
 #endif
+
+#ifdef CONFIG_OPENBLOCKS266
+#define PUSHSW_INT	26
+	if (irq == PUSHSW_INT) {
+		mtdcr(DCRN_UIC_TR(UIC0), 1 << (31 - PUSHSW_INT));
+		mtdcr(DCRN_UIC_SR(UIC0), 1 << (31 - PUSHSW_INT));
+	}
+#endif
+
 	ppc_cached_irq_mask[word] |= 1 << (31 - bit);
 	switch (word) {
 	case 0:
diff -Naur linux-2.6.0-test10/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.0-test10-obs266/arch/ppc/syslib/ppc4xx_setup.c
--- linux-2.6.0-test10/arch/ppc/syslib/ppc4xx_setup.c	Mon Nov 24 10:30:59 2003
+++ linux-2.6.0-test10-obs266/arch/ppc/syslib/ppc4xx_setup.c	Wed Nov 26 18:06:57 2003
@@ -50,6 +50,12 @@
 extern int wdt_enable;
 extern unsigned long wdt_period;
 
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+#include <linux/delay.h>
+extern int obsled_out(int);
+#define BLINK_MSEC	(1000)
+#endif
+
 /* Global Variables */
 bd_t __res;
 
@@ -147,15 +153,22 @@
 {
 	printk("System Halted\n");
 	local_irq_disable();
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	while (1) {
+		obsled_out(7);
+		mdelay(BLINK_MSEC);
+		obsled_out(0);
+		mdelay(BLINK_MSEC);
+	}
+#else
 	while (1) ;
+#endif
 }
 
 static void
 ppc4xx_halt(void)
 {
-	printk("System Halted\n");
-	local_irq_disable();
-	while (1) ;
+	ppc4xx_power_off();
 }
 
 /*
@@ -170,7 +183,9 @@
 	unsigned int freq;
 	bd_t *bip = &__res;
 
-#if defined(CONFIG_WALNUT) || defined(CONFIG_CEDER)|| defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE)
+#if defined(CONFIG_WALNUT) || defined(CONFIG_CEDER)	\
+	|| defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE) \
+	|| defined(CONFIG_OPENBLOCKS266)
 	/* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
 	mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
 #endif
diff -Naur linux-2.6.0-test10/drivers/char/Kconfig linux-2.6.0-test10-obs266/drivers/char/Kconfig
--- linux-2.6.0-test10/drivers/char/Kconfig	Mon Nov 24 10:31:05 2003
+++ linux-2.6.0-test10-obs266/drivers/char/Kconfig	Wed Nov 26 18:16:14 2003
@@ -987,5 +987,21 @@
 	  out to lunch past a certain margin.  It can reboot the system
 	  or merely print a warning.
 
+config X1226_RTC
+	tristate 'X1226 RTC support'
+	depends on I2C
+
+config I2C_EEPROM
+	tristate 'I2C EEPROM support'
+	depends on I2C
+
+config OBS_PUSHSW
+	tristate 'OpenBlockS Push button'
+	depends on OPENBLOCKS266
+
+config OBS_LED
+	tristate 'OpenBlockS LED'
+	depends on OPENBLOCKS266
+
 endmenu
 
diff -Naur linux-2.6.0-test10/drivers/char/Makefile linux-2.6.0-test10-obs266/drivers/char/Makefile
--- linux-2.6.0-test10/drivers/char/Makefile	Mon Nov 24 10:33:17 2003
+++ linux-2.6.0-test10-obs266/drivers/char/Makefile	Wed Nov 26 18:16:41 2003
@@ -59,6 +59,10 @@
 ifeq ($(CONFIG_PPC),)
   obj-$(CONFIG_NVRAM) += nvram.o
 endif
+obj-$(CONFIG_X1226_RTC) += x1226-rtc.o
+obj-$(CONFIG_I2C_EEPROM) += eepromi2c.o
+obj-$(CONFIG_OBS_PUSHSW) += pushsw.o
+obj-$(CONFIG_OBS_LED) += obs_led.o
 obj-$(CONFIG_TOSHIBA) += toshiba.o
 obj-$(CONFIG_I8K) += i8k.o
 obj-$(CONFIG_DS1620) += ds1620.o
diff -Naur linux-2.6.0-test10/drivers/char/eepromi2c.c linux-2.6.0-test10-obs266/drivers/char/eepromi2c.c
--- linux-2.6.0-test10/drivers/char/eepromi2c.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/char/eepromi2c.c	Thu Nov 27 02:57:46 2003
@@ -0,0 +1,435 @@
+/*
+ *  linux/drivers/char/eepromi2c.c
+ *
+ *
+ *  Copyright 
+ *  Author: 2002 AXE Inc.  
+ *     	takawata@axe-inc.co.jp
+ *
+ *  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:
+ *    - implement alarm and periodic IRQ support.
+ *
+ */
+/*
+ *  Based On 
+ *  linux/drivers/char/x1226-rtc.c
+ *
+ *  I2C Real Time Clock Client Driver for Xicor X1226 RTC/Calendar
+ *
+ *  Copyright 2002 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:
+ *    - implement alarm and periodic IRQ support.
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/time.h>
+
+#define EEPROM_MAJOR 240
+struct eepromi2c_private
+{
+	u8 ei2_addr;
+	int ei2_size;
+	int ei2_maxpage;
+	int use_count;
+	unsigned char *tmpbuf;
+	struct i2c_client *ei2_i2c;
+};
+static spinlock_t eeprom_state_lock = SPIN_LOCK_UNLOCKED;
+
+
+struct eepromi2c_private eepromi2c_conf[]=
+{
+	{0x57, 0x200, 64, 0, NULL, NULL},
+	{0x51, 0x2000, 32, 0, NULL, NULL},
+};
+
+#define MAXEEPROMDEVS (sizeof(eepromi2c_conf)/ sizeof(struct eepromi2c_private))
+#ifndef I2C_DRIVER_ID_LARGEEEPROM
+#define I2C_DRIVERID_LARGEEEPROM I2C_DRIVERID_EXP1
+#endif
+#ifndef I2C_M_WR
+#define I2C_M_WR 0x0
+#endif
+
+#ifdef DEBUG_I2CEEPROM
+#define	dbg(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
+#else
+#define	dbg(fmt, args...)
+#endif
+
+#define I2CEEPROM_MODULE_NAME "LARGEEEPROM"
+#define PFX I2CEEPROM_MODULE_NAME
+
+#define err(format, arg...) printk(KERN_ERR PFX ": " format , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format , ## arg)
+#define emerg(format, arg...) printk(KERN_EMERG PFX ": " format , ## arg)
+
+static struct i2c_driver i2ceeprom_driver;
+
+static int i2ceeprom_read(struct i2c_client *client,
+			  u16 reg_offset, u8 *buf, int len)
+{
+	int ret;
+	u8 regbuf[2] = { reg_offset>>8, reg_offset };
+	struct i2c_msg random_addr_read[2] = {
+		{
+			/* "Set Current Address" */
+			client->addr,
+			client->flags | I2C_M_WR,
+			sizeof(regbuf),
+			regbuf
+		},
+		{
+			/* "Sequential Read" if len>1,
+			   "Current Address Read" if len=1 */
+			client->addr ,
+			client->flags| I2C_M_RD ,
+			len,
+			buf
+		}
+	};
+
+	if ((ret = i2c_transfer(client->adapter, random_addr_read, 2)) != 2) {
+		ret = -ENXIO;
+		dbg("i2c_transfer failed\n");
+	}
+
+	return ret;
+}
+
+static int i2ceeprom_write(struct i2c_client *client,
+			   u16 reg_offset, u8 *buf, int len)
+{
+	int ret;
+	u8* local_buf;
+	u8 regbuf[2] = { reg_offset>>8, reg_offset };
+	struct i2c_msg page_write = {
+		client->addr,
+		client->flags ,
+		len + sizeof(regbuf),
+		NULL
+	};
+
+	if ((local_buf = (u8*)kmalloc(len + sizeof(regbuf),
+				      GFP_KERNEL)) == NULL) {
+		err("buffer alloc failed\n");
+		return -ENOMEM;
+	}
+
+	memcpy(local_buf, regbuf, sizeof(regbuf));
+	memcpy(local_buf + sizeof(regbuf), buf, len);
+	page_write.buf = local_buf;
+	
+	if ((ret = i2c_transfer(client->adapter, &page_write, 1)) != 1) {
+		ret = -ENXIO;
+		dbg("i2c_transfer failed\n");
+	}
+
+	kfree(local_buf);
+	return ret;
+}
+
+static long long eepromi2c_llseek(struct file *file, loff_t offset, int origin)
+{
+	int minor;
+	struct inode *minode = file->f_dentry->d_inode;
+	struct eepromi2c_private *pri;
+
+	if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS)
+		return -ENXIO;
+	pri = &eepromi2c_conf[minor];
+	switch (origin) {
+	case 0:
+		file->f_pos = offset;
+		return file->f_pos;
+	case 1:
+		file->f_pos += offset;
+		return file->f_pos;
+	case 2:
+		file->f_pos = pri->ei2_size - offset;
+		return file->f_pos;
+	default:
+		return -EINVAL;
+	}
+}
+
+static ssize_t eepromi2c_read(struct file *file, char *buf, size_t count,
+			      loff_t *ppos)
+{
+	int minor;
+	struct i2c_client *client;
+	struct eepromi2c_private *pri;
+	int offset, remaining, copysize;
+	struct inode *minode = file->f_dentry->d_inode;
+	if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS)
+		return -ENXIO;
+	pri = &eepromi2c_conf[minor];
+	if (!(client = pri->ei2_i2c))
+		return -ENXIO;
+	offset = *ppos;
+	if ((offset + count) > pri->ei2_size)
+		count = pri->ei2_size - offset;
+	if (count <= 0) {
+		return 0;
+	}
+	remaining = count;
+	do {
+		copysize = (remaining > pri->ei2_maxpage)
+				? pri->ei2_maxpage : remaining;
+		dbg("; copysize=%d\n", copysize);	
+		i2ceeprom_read(client, offset, pri->tmpbuf, copysize);
+		if (copy_to_user(buf, pri->tmpbuf, copysize))
+			return -EFAULT;
+		*ppos += copysize;
+		offset += copysize;
+		buf += copysize;
+		remaining -= copysize;
+	} while (remaining > 0);
+	return count;
+}
+
+static ssize_t eepromi2c_write(struct file *file, const char *buf, size_t count,
+			       loff_t *ppos)
+{
+	int minor;
+	struct i2c_client *client;
+	struct eepromi2c_private *pri;
+	int offset, remaining, copysize;
+	struct inode *minode = file->f_dentry->d_inode;
+	if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS)
+		return -ENXIO;
+	pri = &eepromi2c_conf[minor];
+	if (!(client = pri->ei2_i2c))
+		return -ENXIO;
+	offset = *ppos;
+	if ((offset + count) > pri->ei2_size)
+		count = pri->ei2_size - offset;
+	if (count <= 0) {
+		return 0;
+	}
+	/*Write regeon should be aligned */
+	copysize = (count > pri->ei2_maxpage) ? pri->ei2_maxpage : count;
+	if ((offset / pri->ei2_maxpage) !=
+	    ((offset + copysize) / pri->ei2_maxpage))
+		copysize = pri->ei2_maxpage - (offset % pri->ei2_maxpage);
+	dbg("; offset=%d\n", offset);
+	remaining = count;
+	do {
+		dbg("; copysize=%d\n", copysize);
+		if (copy_from_user(pri->tmpbuf, buf, copysize)) {
+			return -EFAULT;
+		}
+
+		i2ceeprom_write(client, offset, pri->tmpbuf, copysize);
+		*ppos += copysize;
+		offset += copysize;
+		buf += copysize;
+		remaining -= copysize;
+		copysize = (remaining > pri->ei2_maxpage)
+				? pri->ei2_maxpage : remaining;
+	} while (remaining > 0);
+	return count;
+}
+
+int eepromi2c_open(struct inode *minode, struct file *mfile)
+{
+	int minor;
+	spin_lock(&eeprom_state_lock);
+	if ((minor = MINOR(minode->i_rdev)) >= MAXEEPROMDEVS)
+		return -ENXIO;
+	if (!eepromi2c_conf[minor].ei2_i2c)
+		return -ENXIO;
+
+	if (eepromi2c_conf[minor].use_count)
+		return -EBUSY;
+	eepromi2c_conf[minor].use_count++;
+	spin_unlock(&eeprom_state_lock);
+	return 0;
+}
+
+static int eepromi2c_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	return -ENOTTY;
+}
+
+static int eepromi2c_release(struct inode *inode, struct file *file)
+{
+	int minor;
+	spin_lock(&eeprom_state_lock);
+	if ((minor = MINOR(inode->i_rdev)) >= MAXEEPROMDEVS)
+		return -ENXIO;
+	eepromi2c_conf[minor].use_count--;
+	spin_unlock(&eeprom_state_lock);
+	return 0;
+}
+
+static struct file_operations eepromi2c_fops = {
+	owner:		THIS_MODULE,
+	llseek:		eepromi2c_llseek,
+	read:		eepromi2c_read,
+	write:		eepromi2c_write,
+	ioctl:		eepromi2c_ioctl,
+	open:		eepromi2c_open,
+	release:	eepromi2c_release,
+};
+
+
+
+
+static int i2ceeprom_probe(struct i2c_adapter *adap)
+{
+	int ret, res, i;
+#if 0
+	char nbuffer[15];
+#endif
+	unsigned char stat;
+	struct i2c_client *this_client;
+
+	res = -ENXIO;
+	register_chrdev(EEPROM_MAJOR, "eepromi2c", &eepromi2c_fops);
+
+	this_client = kmalloc(sizeof(*this_client), GFP_KERNEL);
+
+	for (i = 0; i < MAXEEPROMDEVS; i++) {
+		if (this_client == NULL) {
+			break;
+		}
+		strcpy(this_client->name, I2CEEPROM_MODULE_NAME);
+		this_client->id = i2ceeprom_driver.id;
+		this_client->flags = 0;
+		this_client->addr = eepromi2c_conf[i].ei2_addr;
+		this_client->adapter = adap;
+		this_client->driver = &i2ceeprom_driver;
+
+		if ((res = i2ceeprom_read(this_client, 0, &stat, 1)) < 0) {
+			printk("Probe read %d\n", res);
+			continue;
+		}
+
+		if ((eepromi2c_conf[i].tmpbuf =
+		     kmalloc(eepromi2c_conf[i].ei2_size, GFP_KERNEL)) == NULL) {
+			continue;
+		}
+
+		printk("Serial EEPROM FOUND at %x\n", this_client->addr);
+		if (i2c_attach_client(this_client)) {
+			continue;
+		}
+
+		this_client->data = &eepromi2c_conf[i];
+		eepromi2c_conf[i].ei2_i2c = this_client;
+		ret = 0;	/*At least 1 dev found */
+		this_client = kmalloc(sizeof(*this_client), GFP_KERNEL);
+	}
+	kfree(this_client);
+	return ret;
+}
+
+static int i2ceeprom_detach(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+
+	kfree(client);
+
+	return 0;
+}
+
+static int i2ceeprom_command(struct i2c_client *client, unsigned int cmd,
+			     void *arg)
+{
+
+	return -EINVAL;
+}
+
+
+static struct i2c_driver i2ceeprom_driver = {
+	name:		I2CEEPROM_MODULE_NAME,
+	id:		I2C_DRIVERID_LARGEEEPROM,
+	flags:		I2C_DF_NOTIFY,
+	attach_adapter:	i2ceeprom_probe,
+	detach_client:	i2ceeprom_detach,
+	command:	i2ceeprom_command
+};
+
+
+static __init int i2ceeprom_init(void)
+{
+	int ret;
+	
+	info("I2C based EEPROM driver.\n");
+	ret = i2c_add_driver(&i2ceeprom_driver);
+	if (ret) {
+		err("Register I2C driver failed, errno is %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit i2ceeprom_exit(void)
+{
+	i2c_del_driver(&i2ceeprom_driver);
+}
+
+module_init(i2ceeprom_init);
+module_exit(i2ceeprom_exit);
diff -Naur linux-2.6.0-test10/drivers/char/obs_led.c linux-2.6.0-test10-obs266/drivers/char/obs_led.c
--- linux-2.6.0-test10/drivers/char/obs_led.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/char/obs_led.c	Wed Nov 26 22:52:29 2003
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) AXE,Inc.
+ *	Based on ibm_ocp_gpio.c
+ */
+/*
+ * FILE NAME ibm_ocp_gpio.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ *  API for IBM PowerPC 4xx GPIO device.
+ *  Driver for IBM PowerPC 4xx GPIO device.
+ *
+ *  Armin Kuster akuster@pacbell.net
+ *  Sept, 2001
+ *
+ *  Orignial driver
+ *  Author: MontaVista Software, Inc.  <source@mvista.com>
+ *          Frank Rowand <frank_rowand@mvista.com>
+ *          Debbie Chu   <debbie_chu@mvista.com>
+ *
+ * Copyright 2000,2001,2002 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE	LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	TODO: devfs
+ *
+ *	Version: 02/01/12 - Armin
+ *			 converted to ocp and using ioremap
+ *
+ *	1.2 02/21/01 - Armin
+ *		minor compiler warning fixes
+ *
+ *	1.3 02/22/01 - Armin
+ *		added apm
+ *
+ *	1.4 05/07/02 - Armin/David Mueller
+ *		coverted to core_ocp[];
+ *
+ *	1.5 05/25/02 - Armin
+ *	 name change from *_driver to *_dev
+ *
+ *	1.6 06/04/02 - Matt Porter
+ *	ioremap paddr. Comment as 4xx generic driver.
+ *	Fix header to be userland safe and locate in
+ *	an accessible area.  Add ioctl to configure
+ *	multiplexed GPIO pins.
+ *
+ *	1.7 07/25/02 - Armin
+ *	added CPM to enable/disable in init/exit
+ *
+ */
+
+#define OBSLED_VER	"0.01"
+#define OBSLED_MINOR	171
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/pm.h>
+#include <linux/ibm_ocp_gpio.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+
+/* General purpose i/o */
+
+typedef struct gpio_regs {
+	u32 or;
+	u32 tcr;
+	u32 pad[4];
+	u32 odr;
+	u32 ir;
+} gpio_t;
+
+struct miscdevice obsled_miscdev;
+static gpio_t *gpiop;
+static int is_open = 0;
+
+#define GPIO_BIT(n)	(1 << (31 - (n)))
+#define PAT_1	GPIO_BIT(12)
+#define PAT_2	GPIO_BIT(13)
+#define PAT_4	GPIO_BIT(14)
+
+#define ocp_get_pm(type, num)	(OCP_CPM_NA)
+
+#ifdef CONFIG_PM
+static struct pm_dev *pm_gpio;
+
+static int gpio_save_state(u32 state)
+{
+	return 0;
+}
+
+static int gpio_suspend(u32 state)
+{
+	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | state);
+	return 0;
+}
+
+static int gpio_resume(u32 state)
+{
+	mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~state);
+	return 0;
+}
+#endif
+
+static int obsled_out_reg(int led, u32 *or, u32 *tcr)
+{
+	__u32 data;
+	__u32 mask = PAT_1 | PAT_2 | PAT_4;
+	data = 0;
+	if (led & 1) data |= PAT_1;
+	if (led & 2) data |= PAT_2;
+	if (led & 4) data |= PAT_4;
+
+	*or = (*or & ~mask) | ((~data) & mask);
+	eieio();
+	*tcr = *tcr | mask;
+	eieio();
+	return 0;
+}
+
+int obsled_out_pat(int led)
+{
+#ifdef CONFIG_PM
+	pm_access(pm_gpio);
+#endif
+	return obsled_out_reg(led, &gpiop->or, &gpiop->tcr);
+}
+
+static int obsled_open(struct inode *inode, struct file *file)
+{
+	if (is_open) return -EALREADY;
+	is_open = 1;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static int obsled_release(struct inode *inode, struct file *file)
+{
+	is_open = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static ssize_t obsled_write(struct file *file, const char *buf, size_t count,
+			    loff_t *ppos)
+{
+	int err, i, led;
+
+	if (count <= 0) {
+		return 0;
+	}
+
+	for (i = 0; i < count; i++) {
+		err = get_user(led, buf + i);
+		if (err) {
+			return err;
+		}
+		if (led < '0' || '7' < led) {
+			/* skip */
+			continue;
+		}
+		err = obsled_out_pat(led);
+		if (err) {
+			return err;
+		}
+	}
+
+	return count;
+}
+
+static struct file_operations obsled_fops = {
+	owner:		THIS_MODULE,
+	write:		obsled_write,
+	open:		obsled_open,
+	release:	obsled_release,
+};
+
+static int __init obsled_init(void)
+{
+	int i;
+	struct ocp_device *gpio_dev;
+
+	printk("OBS_LED driver version %s\n", OBSLED_VER);
+
+	for (i = 0; i < ocp_get_num(OCP_FUNC_GPIO); i++) {
+		gpio_dev = ocp_get_dev(OCP_FUNC_GPIO, i);
+		if (!gpio_dev)
+			break;
+
+		obsled_miscdev.minor = OBSLED_MINOR;
+		obsled_miscdev.name = gpio_dev->name;
+		obsled_miscdev.fops = &obsled_fops;
+		misc_register(&obsled_miscdev);
+
+		gpiop = (struct gpio_regs *)ioremap(
+				gpio_dev->paddr, sizeof(struct gpio_regs));
+
+		mtdcr(DCRN_CPMFR,
+			mfdcr(DCRN_CPMFR) & ~ocp_get_pm(OCP_FUNC_GPIO, i));
+
+		printk("OBS_LED: GPIO #%d at 0x%lx\n",
+			       	i, (unsigned long)gpiop);
+	}
+
+	return 0; 
+}
+
+static void __exit obsled_exit(void)
+{
+	int i;
+	struct ocp_device *gpio_dev;
+
+	for (i = 0; i < ocp_get_num(OCP_FUNC_GPIO); i++) {
+		gpio_dev = ocp_get_dev(OCP_FUNC_GPIO, i);
+		misc_deregister(&obsled_miscdev);
+		mtdcr(DCRN_CPMFR,
+			mfdcr(DCRN_CPMFR) | ocp_get_pm(OCP_FUNC_GPIO, i));
+	}
+}
+
+module_init(obsled_init);
+module_exit(obsled_exit);
+
+/* EXPORT_SYMBOL(obsled_out_pat); */
+
+MODULE_LICENSE("GPL");
+
+#define GPIO_OR		((u32 *)0xef600700)
+#define GPIO_TCR	((u32 *)0xef600704)
+
+int obsled_out(int led)
+{
+	return obsled_out_reg(led, GPIO_OR, GPIO_TCR);
+}
+
diff -Naur linux-2.6.0-test10/drivers/char/pushsw.c linux-2.6.0-test10-obs266/drivers/char/pushsw.c
--- linux-2.6.0-test10/drivers/char/pushsw.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/char/pushsw.c	Wed Nov 26 22:45:50 2003
@@ -0,0 +1,149 @@
+/*
+ *	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.
+ *
+ *	Century <www.centurysys.co.jp>
+ *		- Century's push button driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+
+#include "pushsw.h"
+
+#define DBGON(x)	
+#define DBGOFF(x)	x
+
+
+#define PSW_VER		"0.01"
+#define PSW_IRQ		26 /* AIC_INT1 */
+
+static DECLARE_WAIT_QUEUE_HEAD(psw_wait);
+
+/* used to allow only one process at a time to "own" the push switch */
+static pid_t			psw_wait_pid = 0;
+
+static irqreturn_t psw_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* DBGOFF(printk(KERN_CRIT "p");) */
+	wake_up_interruptible(&psw_wait);
+	return IRQ_HANDLED;
+}
+
+static int psw_ioctl(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg)
+{
+	unsigned long	flags;
+
+	if (iminor(inode) != 170)
+		return -ENODEV;
+
+	switch (cmd) {
+	case PSWIOC_GETWAITPID:
+		return put_user(psw_wait_pid, (int *)arg);
+	case PSWIOC_WAITPUSH:
+		/* protect psw_wait_pid */
+		local_irq_save(flags);
+		if (psw_wait_pid == 0) {
+			psw_wait_pid = current->pid;
+			local_irq_restore(flags);
+			DBGOFF(printk("[psw_ioctl] PSWIOC_WAITPUSH pid %u\n", psw_wait_pid);)
+			/* block until switch pushed */
+			interruptible_sleep_on(&psw_wait);
+			local_irq_save(flags);
+			psw_wait_pid = 0;
+			local_irq_restore(flags);
+
+			DBGOFF(printk("[psw_ioctl] unblocked\n");)
+			if (signal_pending(current)) {
+				DBGOFF(printk("[psw_ioctl] sig\n");)
+				return -ERESTARTSYS;
+			}
+			return 0;
+		} else {
+			local_irq_restore(flags);
+			return -EBUSY;
+		}
+	default:
+		break;
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int psw_open(struct inode *inode, struct file *file)
+{
+	if (iminor(inode) != 170)
+		return -ENODEV;
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int psw_release(struct inode *inode, struct file *file)
+{
+	unsigned long	flags;
+
+	if (iminor(inode) != 170)
+		return 0;
+
+	DBGOFF(printk("by pid %u\n", current->pid);)
+	local_irq_save(flags);
+	if (psw_wait_pid && (psw_wait_pid == current->pid)) {
+		psw_wait_pid = 0;
+		local_irq_restore(flags);
+		DBGOFF(printk("cleared\n");)
+	} else {
+		local_irq_restore(flags);
+		DBGOFF(if (psw_wait_pid) printk("psw_wait_pid %u, current->pid %u\n", psw_wait_pid, current->pid);)
+	}
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static struct file_operations	psw_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= psw_ioctl,
+	.open		= psw_open,
+	.release	= psw_release,
+};
+
+static struct miscdevice psw_miscdev = {
+       	170, "pushsw", &psw_fops
+};
+
+static int __init psw_init(void)
+{
+	printk("Push switch driver v%s\n", PSW_VER);
+
+	/* Install the push switch interrupt handler */
+	if (request_irq(PSW_IRQ, psw_isr, SA_INTERRUPT, "push switch", NULL)) {
+		printk("[psw_open] interrupt %u not free\n", PSW_IRQ);
+		return -EIO;
+	}
+	DBGOFF(printk("[psw_init] Push switch installed on interrupt %u\n", PSW_IRQ);)
+	misc_register(&psw_miscdev);
+	return 0;
+}
+
+static void __exit psw_exit(void)
+{
+	misc_deregister(&psw_miscdev);
+	free_irq(PSW_IRQ, NULL);
+}
+
+module_init(psw_init);
+module_exit(psw_exit);
+
diff -Naur linux-2.6.0-test10/drivers/char/pushsw.h linux-2.6.0-test10-obs266/drivers/char/pushsw.h
--- linux-2.6.0-test10/drivers/char/pushsw.h	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/char/pushsw.h	Wed Nov 26 17:49:17 2003
@@ -0,0 +1,19 @@
+/* 
+ *	Century <www.centurysys.co.jp>
+ *		- Century's push switch driver header
+ */
+
+#include <linux/ioctl.h>
+#include <linux/major.h>
+/* #include <linux/miscdevice.h> */
+
+#define PUSHSW_MAJOR		(MISC_MAJOR)
+
+#define	PUSHSW_IOCTL_BASE	'P'
+
+#define	PSWIOC_GETSTATUS	_IOR(PUSHSW_IOCTL_BASE, 0, int)
+#define	PSWIOC_WAITPUSH		_IOR(PUSHSW_IOCTL_BASE, 1, int)
+#define	PSWIOC_GETWAITPID	_IOR(PUSHSW_IOCTL_BASE, 2, int)
+
+#define PSWIOF_PUSHED		(1)
+#define PSWIOF_NOTPUSHED	(0)
diff -Naur linux-2.6.0-test10/drivers/char/tty_io.c linux-2.6.0-test10-obs266/drivers/char/tty_io.c
--- linux-2.6.0-test10/drivers/char/tty_io.c	Mon Nov 24 10:32:08 2003
+++ linux-2.6.0-test10-obs266/drivers/char/tty_io.c	Wed Nov 26 18:20:15 2003
@@ -111,7 +111,11 @@
 struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
 	.c_iflag = ICRNL | IXON,
 	.c_oflag = OPOST | ONLCR,
+#ifdef CONFIG_OPENBLOCKS266
+	.c_cflag = B9600 | CS8 | CREAD | HUPCL,
+#else
 	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
+#endif
 	.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK |
 		   ECHOCTL | ECHOKE | IEXTEN,
 	.c_cc = INIT_C_CC
diff -Naur linux-2.6.0-test10/drivers/char/x1226-rtc.c linux-2.6.0-test10-obs266/drivers/char/x1226-rtc.c
--- linux-2.6.0-test10/drivers/char/x1226-rtc.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/char/x1226-rtc.c	Thu Nov 27 03:09:44 2003
@@ -0,0 +1,555 @@
+/*
+ *  linux/drivers/char/x1226-rtc.c
+ *
+ *  I2C Real Time Clock Client Driver for Xicor X1226 RTC/Calendar
+ *
+ *  Copyright 2002 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:
+ *    - implement alarm and periodic IRQ support.
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/time.h>
+
+#undef DEBUG_X1226
+
+#ifdef DEBUG_X1226
+#define	dbg(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
+#else
+#define	dbg(fmt, args...)
+#endif
+
+#define X1226_MODULE_NAME "X1226"
+#define PFX X1226_MODULE_NAME
+#ifndef I2C_DRIVERID_X1226
+#define I2C_DRIVERID_X1226  I2C_DRIVERID_EXP0
+#endif
+
+#define err(format, arg...) printk(KERN_ERR PFX ": " format , ## arg)
+#define info(format, arg...) printk(KERN_INFO PFX ": " format , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING PFX ": " format , ## arg)
+#define emerg(format, arg...) printk(KERN_EMERG PFX ": " format , ## arg)
+
+#define EPOCH 2000
+#define SYS_EPOCH 1900
+
+#undef BCD_TO_BIN
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+
+#undef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
+
+#define X1226_RTC_SR      0x3f
+#define   RTC_SR_RTCF  (1)
+#define   RTC_SR_WEL  (1<<1)
+#define   RTC_SR_RWEL (1<<2)
+
+#define X1226_RTC_BASE    0x30
+
+/* This is an image of the RTC registers starting at offset 0x30 */
+struct rtc_registers {
+	unsigned char secs;  // 30
+        unsigned char mins;  // 31
+        unsigned char hours; // 32
+        unsigned char day;   // 33
+        unsigned char mon;   // 34
+        unsigned char year;  // 35
+        unsigned char dayofweek; // 36
+        unsigned char epoch; // 37
+};
+
+#define X1226_CONTROL_DTR  0x13
+#define X1226_CONTROL_ATR  0x12
+#define X1226_CONTROL_INT  0x11
+#define X1226_CONTROL_BL   0x10
+
+#define DEVID_RTC          0x6F
+#define DEVID_NVRAM        0x57
+#define   SLAVE_READ 0x01
+#ifndef I2C_M_WR
+#define I2C_M_WR 0x0
+#endif
+#define ABITS           9
+#define EESIZE          (1 << ABITS)    /* size in bytes */
+
+#define NVSIZE          512             /* we use 512 bytes */
+#define NVOFFSET        (EESIZE-NVSIZE) /* at end of EEROM */
+
+static struct i2c_driver x1226_driver;
+
+static int x1226_use_count = 0;
+
+static struct i2c_client *this_client = NULL;
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data);
+
+
+static int x1226_read (struct i2c_client *client,
+		       u8 reg_offset, u8* buf, int len)
+{
+	int ret;
+	u8 regbuf[2] = { 0, reg_offset };
+	struct i2c_msg random_addr_read[2] = {
+		{
+			/* "Set Current Address" */
+			client->addr,
+			client->flags | I2C_M_WR,
+			sizeof(regbuf),
+			regbuf
+		},
+		{
+			/* "Sequential Read" if len>1,
+			   "Current Address Read" if len=1 */
+			client->addr,
+			client->flags | I2C_M_RD,
+			len,
+			buf
+		}
+	};
+
+	if ((ret = i2c_transfer(client->adapter, random_addr_read, 2)) != 2) {
+		ret = -ENXIO;
+		dbg("i2c_transfer failed\n");
+	}
+
+	return ret;
+}
+
+static int x1226_write (struct i2c_client *client,
+			u8 reg_offset, u8* buf, int len)
+{
+	int ret;
+	u8* local_buf;
+	u8 regbuf[2] = { 0, reg_offset };
+	struct i2c_msg page_write = {
+		client->addr,
+		client->flags,
+		len + sizeof(regbuf),
+		NULL
+	};
+
+	if ((local_buf = (u8*)kmalloc(len + sizeof(regbuf),
+				      GFP_KERNEL)) == NULL) {
+		err("buffer alloc failed\n");
+		return -ENOMEM;
+	}
+
+	memcpy(local_buf, regbuf, sizeof(regbuf));
+	memcpy(local_buf + sizeof(regbuf), buf, len);
+	page_write.buf = local_buf;
+	
+	if ((ret = i2c_transfer(client->adapter, &page_write, 1)) != 1) {
+		ret = -ENXIO;
+		dbg("i2c_transfer failed\n");
+	}
+
+	kfree(local_buf);
+	return ret;
+}
+
+
+static int ccr_write_enable(struct i2c_client *client)
+{
+	u8 sr = RTC_SR_WEL;
+	int ret;
+	
+	if ((ret = x1226_write(client, X1226_RTC_SR, &sr, 1)) < 0)
+		return ret;
+	sr |= RTC_SR_RWEL;
+	if ((ret = x1226_write(client, X1226_RTC_SR, &sr, 1)) < 0)
+		return ret;
+	sr = 0;
+	if ((ret = x1226_read(client, X1226_RTC_SR, &sr, 1)) < 0)
+		return ret;
+
+	sr &= (RTC_SR_RWEL | RTC_SR_RWEL);
+	if (sr != (RTC_SR_RWEL | RTC_SR_RWEL)) {
+		dbg("verify SR failed\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static int ccr_write_disable(struct i2c_client *client)
+{
+	int ret;
+	u8 sr = 0;
+	
+	if ((ret = x1226_write(client, X1226_RTC_SR, &sr, 1)) < 0)
+		return ret;
+	if ((ret = x1226_read(client, X1226_RTC_SR, &sr, 1)) < 0)
+		return ret;
+	if (sr != 0) {
+		dbg("verify SR failed\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+
+static int
+x1226_get_time(struct i2c_client *client, struct rtc_time *tm)
+{	
+	struct rtc_registers rtc;
+	u32 epoch;
+	int ret;
+	
+	/* read RTC registers */
+	if ((ret = x1226_read(client, X1226_RTC_BASE, (u8*)&rtc,
+			      sizeof(struct rtc_registers))) < 0) {
+		dbg("couldn't read RTC\n");
+		return ret;
+	}
+
+	dbg("IN: epoch=%02x, year=%02x, mon=%02x, day=%02x, hour=%02x, "
+	    "min=%02x, sec=%02x\n",
+	    rtc.epoch, rtc.year, rtc.mon, rtc.day, rtc.hours,
+	    rtc.mins, rtc.secs);
+	
+	epoch  = 100 * BCD_TO_BIN(rtc.epoch);   // 19 / 20
+	tm->tm_year = BCD_TO_BIN(rtc.year); // 0 - 99
+	tm->tm_year += (epoch - SYS_EPOCH);
+	tm->tm_mon = BCD_TO_BIN(rtc.mon);   // 1 - 12
+	tm->tm_mon--;                       /* tm_mon is 0 to 11 */
+	tm->tm_mday = BCD_TO_BIN(rtc.day);  // 1 - 31
+	tm->tm_hour = BCD_TO_BIN(rtc.hours & ~0x80);
+	if (!(rtc.hours & 0x80)) {
+		// AM/PM 1-12 format, convert to MIL
+		tm->tm_hour--; // 0 - 11
+		if (rtc.hours & (1<<5))
+			tm->tm_hour += 12; // PM
+	}
+	
+	tm->tm_min = BCD_TO_BIN(rtc.mins);
+	tm->tm_sec = BCD_TO_BIN(rtc.secs);
+
+	dbg("OUT: year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
+	    tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+	    tm->tm_min, tm->tm_sec);
+	
+	return 0;
+}
+
+static int 
+x1226_set_time(struct i2c_client *client, const struct rtc_time *tm)
+{
+	struct rtc_registers rtc;
+	int ret;
+
+	dbg("IN: year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
+	    tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+	    tm->tm_min, tm->tm_sec);
+
+	rtc.epoch = BIN_TO_BCD(EPOCH/100);
+	rtc.year  = BIN_TO_BCD(tm->tm_year + SYS_EPOCH - EPOCH);
+	rtc.mon   = BIN_TO_BCD(tm->tm_mon + 1); /* tm_mon is 0 to 11 */
+	rtc.day   = BIN_TO_BCD(tm->tm_mday);
+	rtc.dayofweek = 0; // ignore day of week
+	rtc.hours = BIN_TO_BCD(tm->tm_hour) | 0x80; /* 24 hour format */
+	rtc.mins  = BIN_TO_BCD(tm->tm_min);
+	rtc.secs  = BIN_TO_BCD(tm->tm_sec);
+	
+	dbg("OUT: epoch=%02x, year=%02x, mon=%02x, day=%02x, hour=%02x, "
+	    "min=%02x, sec=%02x\n",
+	    rtc.epoch, rtc.year, rtc.mon, rtc.day, rtc.hours,
+	    rtc.mins, rtc.secs);
+	
+	/* write RTC registers */
+	if ((ret = ccr_write_enable(client)) < 0)
+		return ret;
+	if ((ret = x1226_write(client, X1226_RTC_BASE, (u8*)&rtc,
+			       sizeof(struct rtc_registers))) < 0) {
+		dbg("couldn't write RTC\n");
+		return ret;
+	}
+	ccr_write_disable(client);
+
+	return 0;
+}
+
+
+static int
+x1226_probe(struct i2c_adapter *adap)
+{
+	int ret;
+        char stat;
+	unsigned char crs[4];
+	struct rtc_time dummy_tm={0,0,0, 1, 0, 100, 0, 0};
+	
+	if (this_client != NULL)
+		return -EBUSY;
+	
+	this_client = kmalloc(sizeof(*this_client), GFP_KERNEL);
+	if (this_client == NULL) {
+		return -ENOMEM;
+	}
+
+	strcpy(this_client->name, X1226_MODULE_NAME);
+	this_client->id		= x1226_driver.id;
+
+        this_client->flags      = 0;
+	this_client->addr       = DEVID_RTC;
+	this_client->adapter    = adap;
+	this_client->driver     = &x1226_driver;
+	this_client->data       = NULL;
+
+	/*
+	 * use x1226_get_time() to probe for an X1226 on this bus.
+	 */
+	if((ret = x1226_read(this_client,X1226_RTC_SR, &stat, 1))< 0){
+		kfree(this_client);
+		this_client = NULL;
+		return ret;
+	}
+
+	info("found X1226 on %s\n", adap->name);
+
+        if(stat & RTC_SR_RTCF){
+	  printk("X1226:Timer Not Initialized after power fail. Setting 2002/1/1/0:00\n" );
+	  ret= x1226_set_time(this_client, &dummy_tm);
+	}
+	dbg("stat %x \n", stat);
+	x1226_read(this_client,0x10, &crs[0], 1);
+	x1226_read(this_client,0x11, &crs[1], 1);
+	x1226_read(this_client,0x12, &crs[2], 1);
+	x1226_read(this_client,0x13, &crs[3], 1);
+	dbg("CTLREG:%d %x %x %x %x\n", ret, crs[0],crs[1],crs[2],crs[3]);
+
+	if ((ret = x1226_get_time(this_client, &dummy_tm)) < 0) {
+	  printk("Fetch Timer Failed\n");
+	}else{
+#ifdef DEBUG_X1226
+	  struct rtc_time *tm = &dummy_tm;
+	  dbg("OUT: year=%d, mon=%d, day=%d, hour=%d, min=%d, sec=%d\n",
+	    tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+	    tm->tm_min, tm->tm_sec);
+#endif
+	}
+
+	/* attach it. */
+	return i2c_attach_client(this_client);
+}
+
+static int
+x1226_detach(struct i2c_client *client)
+{
+	i2c_detach_client(client);
+
+	if (this_client != NULL) {
+		kfree(this_client);
+		this_client = NULL;
+	}
+
+	return 0;
+}
+
+int rtc_open(struct inode *minode, struct file *mfile)
+{
+	/*if(MOD_IN_USE)*/
+	if(x1226_use_count > 0) {
+		return -EBUSY;
+	}
+	MOD_INC_USE_COUNT;
+	++x1226_use_count;
+	return 0;
+}
+
+int rtc_release(struct inode *minode, struct file *mfile)
+{
+	MOD_DEC_USE_COUNT;
+	--x1226_use_count;
+	return 0;
+}
+
+static loff_t rtc_llseek(struct file *mfile, loff_t offset, int origint)
+{
+	return -ESPIPE;
+}
+
+static int
+x1226_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	return -EINVAL;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		     unsigned long arg)
+{
+	struct rtc_time rtc_tm;
+	int ret;
+	
+	switch (cmd) {
+	case RTC_RD_TIME:	/* Read the time/date from RTC  */
+		if ((ret = x1226_get_time(this_client, &rtc_tm)) < 0)
+			return ret;
+		return copy_to_user((void *)arg, &rtc_tm, sizeof(rtc_tm)) ? 
+			-EFAULT : 0;
+	case RTC_SET_TIME:	/* Set the RTC */
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&rtc_tm, 
+				   (struct rtc_time *) arg,
+		                   sizeof(struct rtc_time))) 
+			return -EFAULT;
+
+		return x1226_set_time(this_client, &rtc_tm);
+	default:
+		return -EINVAL;
+	}
+}
+
+
+static struct i2c_driver x1226_driver = {
+	name:		X1226_MODULE_NAME,
+	id:		I2C_DRIVERID_X1226,
+	flags:		I2C_DF_NOTIFY,
+	attach_adapter:	x1226_probe,
+	detach_client:	x1226_detach,
+	command:	x1226_command
+};
+
+static struct file_operations rtc_fops = {
+	owner:		THIS_MODULE,
+	llseek:		rtc_llseek,
+	ioctl:		rtc_ioctl,
+	open:		rtc_open,
+	release:	rtc_release,
+};
+
+static struct miscdevice x1226rtc_miscdev = {
+	RTC_MINOR,
+	"rtc",
+	&rtc_fops
+};
+
+static __init int x1226_init(void)
+{
+	int ret;
+
+	info("I2C based RTC driver.\n");
+	ret = i2c_add_driver(&x1226_driver);
+	if (ret) {
+		err("Register I2C driver failed, errno is %d\n", ret);
+		return ret;
+	}
+	ret = misc_register(&x1226rtc_miscdev);
+	if (ret) {
+		err("Register misc driver failed, errno is %d\n", ret);
+		ret = i2c_del_driver(&x1226_driver);
+		if (ret) {
+			err("Unregister I2C driver failed, errno is %d\n",
+			    ret);
+		}
+		return ret;
+	}
+
+	create_proc_read_entry("driver/rtc", 0, 0, rtc_read_proc, NULL);
+
+	return 0;
+}
+
+static void __exit x1226_exit(void)
+{
+        remove_proc_entry("driver/rtc", NULL);
+        misc_deregister(&x1226rtc_miscdev);
+	i2c_del_driver(&x1226_driver);
+}
+
+
+module_init(x1226_init);
+module_exit(x1226_exit);
+
+/*
+ *	Info exported via "/proc/driver/rtc".
+ */
+
+static int rtc_proc_output(char *buf)
+{
+	char *p;
+	struct rtc_time tm;
+	int ret;
+	
+	if ((ret = x1226_get_time(this_client, &tm)) < 0)
+		return ret;
+
+	p = buf;
+
+	/*
+	 * There is no way to tell if the luser has the RTC set for local
+	 * time or for Universal Standard Time (GMT). Probably local though.
+	 */
+	p += sprintf(p,
+		     "rtc_time\t: %02d:%02d:%02d\n"
+		     "rtc_date\t: %04d-%02d-%02d\n"
+		     "rtc_epoch\t: %04d\n",
+		     tm.tm_hour, tm.tm_min, tm.tm_sec,
+		     tm.tm_year + SYS_EPOCH, tm.tm_mon + 1,
+		     tm.tm_mday, EPOCH);
+
+	return p - buf;
+}
+
+static int rtc_read_proc(char *page, char **start, off_t off,
+			 int count, int *eof, void *data)
+{
+	int len = rtc_proc_output(page);
+	if (len <= off + count)
+		*eof = 1;
+	*start = page + off;
+	len -= off;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+	return len;
+}
+
+MODULE_AUTHOR("Steve Longerbeam");
+MODULE_LICENSE("GPL");
+
diff -Naur linux-2.6.0-test10/drivers/i2c/Makefile linux-2.6.0-test10-obs266/drivers/i2c/Makefile
--- linux-2.6.0-test10/drivers/i2c/Makefile	Mon Nov 24 10:31:04 2003
+++ linux-2.6.0-test10-obs266/drivers/i2c/Makefile	Wed Nov 26 22:16:45 2003
@@ -5,4 +5,6 @@
 obj-$(CONFIG_I2C)		+= i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
-obj-y				+= busses/ chips/ algos/
+#obj-y				+= busses/ chips/ algos/
+
+obj-$(CONFIG_I2C_IBM_IIC)       += i2c-algo-ibm_ocp.o i2c-algo-ibm_ocp.o i2c-adap-ibm_ocp.o
diff -Naur linux-2.6.0-test10/drivers/i2c/busses/Makefile linux-2.6.0-test10-obs266/drivers/i2c/busses/Makefile
--- linux-2.6.0-test10/drivers/i2c/busses/Makefile	Mon Nov 24 10:31:08 2003
+++ linux-2.6.0-test10-obs266/drivers/i2c/busses/Makefile	Wed Nov 26 21:29:53 2003
@@ -10,7 +10,7 @@
 obj-$(CONFIG_I2C_ELV)		+= i2c-elv.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
 obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
-obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
+#obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
 obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
diff -Naur linux-2.6.0-test10/drivers/i2c/i2c-adap-ibm_ocp.c linux-2.6.0-test10-obs266/drivers/i2c/i2c-adap-ibm_ocp.c
--- linux-2.6.0-test10/drivers/i2c/i2c-adap-ibm_ocp.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/i2c/i2c-adap-ibm_ocp.c	Thu Nov 27 02:53:43 2003
@@ -0,0 +1,324 @@
+/*
+   -------------------------------------------------------------------------
+   i2c-adap-ibm_ocp.c i2c-hw access for the IIC peripheral on the IBM PPC 405
+   -------------------------------------------------------------------------
+  
+   Current Maintainers:
+   Ian DaSilva and Armin Kuster, MontaVista Software, Inc.
+   idasilva@mvista.com , akuster@mvista.com or source@mvista.com
+
+   Copyright 2000-2002 MontaVista Software Inc.
+
+   Changes made to support the IIC peripheral on the IBM PPC 405 
+
+   ----------------------------------------------------------------------------
+   This file was highly leveraged from i2c-elektor.c, which was created
+   by Simon G. Vogl and Hans Berglund:
+
+ 
+     Copyright (C) 1995-97 Simon G. Vogl
+                   1998-99 Hans Berglund
+
+   With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+   Frodo Looijaard <frodol@dds.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   ----------------------------------------------------------------------------
+
+   History: 01/20/12 - Armin
+   	akuster@mvista.com
+   	ported up to 2.4.16+	
+
+   Version 02/03/25 - Armin
+       converted to ocp format
+       removed commented out or #if 0 code
+
+   Version 1.3: 04/25/02
+   	coverted c++ stlye comments to c
+	added IIC_DEV macro
+	the i2c_adapter->algo_data is a pointer to the iic_algo_i2c_data struct
+	the i2c_adapter->data is a pointer to the ocp_struct for the i2c device
+	general cleanups
+
+    Version 1.4: 04/30/02 
+	added IIC_PORT_DNFS
+    Version 1.5: 05/02/02
+	fixed mem leak added ocp_dev_free if ocp_reg failed
+
+    Version: 1.6 - Armin
+       no longer need extern const paddr structs
+
+    Version: 1.8 - Armin
+       name change of ocp_get_dev
+       name change for *_driver to *_dev
+
+   TODO: add PM hooks
+    
+*/
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <asm/io.h>
+#include <asm/ocp.h>
+
+/*
+ * This next section is configurable, and it is used to set the number
+ * of i2c controllers in the system.  The default number of instances is 1,
+ * however, this should be changed to reflect your system's configuration.
+ */
+
+static int i2c_debug = 0;
+static wait_queue_head_t iic_wait[2];
+static int iic_pending;
+
+extern int i2c_iic_add_bus(struct i2c_adapter *adap);
+extern int i2c_iic_del_bus(struct i2c_adapter *adap);
+
+typedef struct iic_regs {
+	u16 mdbuf;
+	u16 sbbuf;
+	u8 lmadr;
+	u8 hmadr;
+	u8 cntl;
+	u8 mdcntl;
+	u8 sts;
+	u8 extsts;
+	u8 lsadr;
+	u8 hsadr;
+	u8 clkdiv;
+	u8 intmsk;
+	u8 xfrcnt;
+	u8 xtcntlss;
+	u8 directcntl;
+} iic_t;
+
+/* ----- global defines -----------------------------------------------	*/
+#define DEB(x)	if (i2c_debug>=1) x
+#define DEB2(x) if (i2c_debug>=2) x
+#define DEB3(x) if (i2c_debug>=3) x
+#define DEBE(x)	x		/* error messages                               */
+
+#define IIC_DEV(x)	((struct ocp_device *)adap->data)->x
+
+/* ----- local functions ----------------------------------------------	*/
+
+/*
+ * Description:  Put this process to sleep.  We will wake up when the
+ * IIC controller interrupts.
+ */
+void
+iic_ibmocp_waitforpin(void *data)
+{
+
+	unsigned long flags;
+	int timeout = 2;
+	struct ocp_device *iic_dev;
+
+	iic_dev = (struct ocp_device *) data;
+
+	/*
+	 * If interrupts are enabled (which they are), then put the process to
+	 * sleep.  This process will be awakened by two events -- either the
+	 * the IIC peripheral interrupts or the timeout expires. 
+	 */
+	if (iic_dev->irq > 0) {
+		local_irq_save(flags);
+		if (iic_pending == 0) {
+			interruptible_sleep_on_timeout(&
+						       (iic_wait[iic_dev->num]),
+						       timeout * HZ);
+		} else
+			iic_pending = 0;
+		local_irq_restore(flags);
+	} else {
+	/*
+	 * If interrupts are not enabled then delay for a reasonable amount
+	 * of time and return.  We expect that by time we return to the calling
+	 * function that the IIC has finished our requested transaction and
+	 * the status bit reflects this.
+	 * 
+	 * udelay is probably not the best choice for this since it is
+	 * the equivalent of a busy wait
+	 */
+		udelay(100);
+	}
+}
+
+/*
+ * Description: The registered interrupt handler
+ */
+static irqreturn_t
+iic_ibmocp_handler(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+	int ret;
+	struct iic_regs *iic;
+	struct ocp_device *iic_dev;
+
+	iic_dev = (struct ocp_device *) dev_id;
+	iic = (struct iic_regs *) iic_dev->vaddr;
+
+	iic_pending = 1;
+
+	DEB2(printk("iic_ibmocp_handler: in interrupt handler\n"));
+	/* Read status register */
+	ret = readb((int) &(iic->sts));
+	DEB2(printk("iic_ibmocp_handler: status = %x\n", ret));
+	/* Clear status register.  See IBM PPC 405 reference manual for details */
+	writeb(0x0a, (int) &(iic->sts));
+	wake_up_interruptible(&(iic_wait[iic_dev->num]));
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Description: Release irq and memory
+ */
+static void
+iic_ibmocp_release(void)
+{
+	int i;
+	struct ocp_device *iic_dev;
+
+	for (i = 0; i < ocp_get_num(OCP_FUNC_IIC); i++) {
+		iic_dev = ocp_get_dev(OCP_FUNC_IIC, i);
+		if (iic_dev && iic_dev->irq > 0) {
+			disable_irq(iic_dev->irq);
+			free_irq(iic_dev->irq, 0);
+		}
+	}
+
+}
+
+/*
+ * Description: Does nothing
+ */
+static int
+iic_ibmocp_reg(struct i2c_client *client)
+{
+	return 0;
+}
+
+/*
+ * Description: Does nothing
+ */
+static int
+iic_ibmocp_unreg(struct i2c_client *client)
+{
+	return 0;
+}
+
+/*
+ * Description: Called when the module is loaded.  This function starts the
+ * cascade of calls up through the heirarchy of i2c modules (i.e. up to the
+ *  algorithm layer and into to the core layer)
+ */
+static int __init
+iic_ibmocp_init(void)
+{
+	int i;
+	struct ocp_device *iic_dev;
+	struct i2c_adapter *adap;
+
+	printk(KERN_INFO "IBM on-chip iic adapter module\n");
+	
+	for (i = 0; i < ocp_get_num(OCP_FUNC_IIC); i++) {
+		iic_dev = ocp_get_dev(OCP_FUNC_IIC, i);
+		if (!iic_dev)
+			return -ENODEV;
+
+		adap = kmalloc(sizeof(*adap), GFP_KERNEL);
+		if (!adap) {
+			printk(KERN_CRIT
+				"ibm-iic: faild to allocate device data\n"); 
+			return -ENOMEM;
+		}
+
+		memset(adap, 0, sizeof(*adap));
+		iic_dev->ocpdev = adap;
+
+		iic_dev->vaddr
+		       	= ioremap(iic_dev->paddr, sizeof(struct iic_regs));
+		if (!iic_dev) {
+			printk(KERN_CRIT
+			       	"ibm-iic: failed to ioremap device registers\n");
+			return -ENXIO;
+		}
+
+		strcpy(adap->name, "IBM OCP IIC adapter");
+		adap->data = (void *)iic_dev;
+		adap->id = I2C_HW_OCP;
+		adap->algo = NULL;
+		adap->client_register = iic_ibmocp_reg;
+		adap->client_unregister = iic_ibmocp_unreg;
+
+		init_waitqueue_head(&(iic_wait[i]));
+
+		if (iic_dev->irq > 0) {
+			int ret;
+			ret = request_irq(iic_dev->irq, iic_ibmocp_handler, 0,
+					  "IBM OCP IIC", iic_dev);
+			if (ret) {
+				printk(KERN_ERR "IIC: Request irq%d failed\n",
+					iic_dev->irq);
+				iic_dev->irq = 0;
+			}
+		}
+
+		if (i2c_iic_add_bus(adap) < 0)
+			return -ENODEV;
+	}
+
+	return 0; 
+}
+
+static void
+iic_ibmocp_exit(void)
+{
+	int i;
+	struct ocp_device *iic_dev;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < ocp_get_num(OCP_FUNC_IIC); i++) {
+		iic_dev = ocp_get_dev(OCP_FUNC_IIC, i);
+		if (!iic_dev) return;
+
+		adap = (struct i2c_adapter *)iic_dev->ocpdev;
+		if (adap)
+			i2c_iic_del_bus(adap);
+	}
+
+	iic_ibmocp_release();
+}
+
+EXPORT_SYMBOL(iic_ibmocp_waitforpin);
+/*
+ * If modules is NOT defined when this file is compiled, then the MODULE_*
+ * macros will resolve to nothing
+ */
+MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for IBM OCP IIC bus adapter");
+MODULE_PARM(i2c_debug, "i");
+MODULE_LICENSE("GPL");
+
+module_init(iic_ibmocp_init);
+module_exit(iic_ibmocp_exit);
diff -Naur linux-2.6.0-test10/drivers/i2c/i2c-algo-ibm_ocp.c linux-2.6.0-test10-obs266/drivers/i2c/i2c-algo-ibm_ocp.c
--- linux-2.6.0-test10/drivers/i2c/i2c-algo-ibm_ocp.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/i2c/i2c-algo-ibm_ocp.c	Thu Nov 27 02:04:06 2003
@@ -0,0 +1,991 @@
+/*
+   -------------------------------------------------------------------------
+   i2c-algo-ibm_ocp.c i2c driver algorithms for IBM PPC 405 adapters	    
+   -------------------------------------------------------------------------
+      
+   current Mainainers
+   Ian DaSilva and Armin Kuster, MontaVista Software, Inc.
+   idasilva@mvista.com, Akuster@mvista.com or source@mvista.com
+
+   Copyright 2000-2002 MontaVista Software Inc.
+
+   Changes made to support the IIC peripheral on the IBM PPC 405
+
+   ---------------------------------------------------------------------------
+   This file was highly leveraged from i2c-algo-pcf.c, which was created
+   by Simon G. Vogl and Hans Berglund:
+
+     Copyright (C) 1995-1997 Simon G. Vogl
+                   1998-2000 Hans Berglund
+
+   With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and 
+   Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
+   <mbailey@littlefeet-inc.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.
+   ---------------------------------------------------------------------------
+
+   History: 01/20/12 - Armin
+   	akuster@mvista.com
+   	ported up to 2.4.16+	
+
+   Version 02/03/25 - Armin
+       converted to ocp format
+       removed commented out or #if 0 code
+       added Gérard Basler's fix to iic_combined_transaction() such that it 
+       returns the number of successfully completed transfers .
+
+   Version 04/29/03 - Armin
+   	General cleanups
+	changes c++ style comments to c
+	converted to ocp
+	deleted unused printk's
+	Added scan routine from Andrew May
+
+   Version 05/25/02 - Armin
+      name change for *_driver to *_dev
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+
+#include <linux/i2c.h>
+#include <asm/ocp.h>
+
+#include <asm/ibm4xx.h>
+#include <asm/bootinfo.h>
+#define IIC_VER	"2002.30.04"
+
+/* ----- global defines ----------------------------------------------- */
+#define DEB(x) if (i2c_debug>=1) x
+#define DEB2(x) if (i2c_debug>=2) x
+#define DEB3(x) if (i2c_debug>=3) x	/* print several statistical values */
+#define DEBPROTO(x) if (i2c_debug>=9) x;
+	/* debug the protocol by showing transferred bits */
+#define DEF_TIMEOUT 5
+
+#define IIC_DEV(x)	((struct ocp_device *)adap->data)->x
+
+/* ----- global variables ---------------------------------------------	*/
+
+#ifdef SLO_IO
+int jif;
+#endif
+
+/* module parameters:
+ */
+static int i2c_debug = 0;
+static int iic_scan = 0;	/* have a look at what's hanging 'round         */
+
+/* --- setting states on the bus with the right timing: ---------------	*/
+
+#define iic_outb( reg, val) writeb(val,&(reg))
+#define iic_inb( reg) readb(&(reg))
+
+#define IICO_I2C_SDAHIGH	0x0780
+#define IICO_I2C_SDALOW		0x0781
+#define IICO_I2C_SCLHIGH	0x0782
+#define IICO_I2C_SCLLOW		0x0783
+#define IICO_I2C_LINEREAD	0x0784
+
+#define IIC_SINGLE_XFER		0
+#define IIC_COMBINED_XFER	1
+
+#define IIC_ERR_LOST_ARB        -2
+#define IIC_ERR_INCOMPLETE_XFR  -3
+#define IIC_ERR_NACK            -1
+#define IIC_TIMEOUT		100
+#define IIC_RETRY		3
+
+extern void iic_ibmocp_waitforpin(void *data);
+
+typedef struct iic_regs {
+	u16 mdbuf;
+	u16 sbbuf;
+	u8 lmadr;
+	u8 hmadr;
+	u8 cntl;
+	u8 mdcntl;
+	u8 sts;
+	u8 extsts;
+	u8 lsadr;
+	u8 hsadr;
+	u8 clkdiv;
+	u8 intmsk;
+	u8 xfrcnt;
+	u8 xtcntlss;
+	u8 directcntl;
+} iic_t;
+
+/* --- other auxiliary functions --------------------------------------	*/
+
+/*
+ *Description: Puts this process to sleep for a period equal to timeout 
+ */
+static inline void
+iic_sleep(unsigned long timeout)
+{
+	schedule_timeout(timeout * HZ);
+}
+
+/*
+ * Description: This performs the IBM PPC 405 IIC initialization sequence
+ * as described in the PPC405GP data book.
+ */
+static int
+iic_init(struct i2c_adapter *adap)
+{
+	struct iic_regs *iic;
+	unsigned short retval;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	/* Clear master low master address */
+	iic_outb(iic->lmadr, 0);
+
+	/* Clear high master address */
+	iic_outb(iic->hmadr, 0);
+
+	/* Clear low slave address */
+	iic_outb(iic->lsadr, 0);
+
+	/* Clear high slave address */
+	iic_outb(iic->hsadr, 0);
+
+	/* Clear status */
+	iic_outb(iic->sts, 0x0a);
+
+	/* Clear extended status */
+	iic_outb(iic->extsts, 0x8f);
+
+	/* Set clock division */
+	iic_outb(iic->clkdiv, 0x04);
+
+	retval = iic_inb(iic->clkdiv);
+	DEB(printk("iic_init: CLKDIV register = %x\n", retval));
+
+	/* Enable interrupts on Requested Master Transfer Complete */
+	iic_outb(iic->intmsk, 0x01);
+
+	/* Clear transfer count */
+	iic_outb(iic->xfrcnt, 0x0);
+
+	/* Clear extended control and status */
+	iic_outb(iic->xtcntlss, 0xf0);
+
+	/* Set mode control (flush master data buf, enable hold SCL, exit */
+	/* unknown state.                                                 */
+	iic_outb(iic->mdcntl, 0x47);
+
+	/* Clear control register */
+	iic_outb(iic->cntl, 0x0);
+
+	DEB2(printk(KERN_DEBUG "iic_init: Initialized IIC on PPC 405\n"));
+	return 0;
+}
+
+/*
+ * Description: After we issue a transaction on the IIC bus, this function
+ * is called.  It puts this process to sleep until we get an interrupt from
+ * from the controller telling us that the transaction we requested in complete.
+ */
+static int
+wait_for_pin(struct i2c_adapter *adap, int *status)
+{
+
+	int timeout = DEF_TIMEOUT;
+	int retval;
+	struct iic_regs *iic;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	*status = iic_inb(iic->sts);
+#ifndef STUB_I2C
+
+	while (timeout-- && (*status & 0x01)) {
+		iic_ibmocp_waitforpin(adap->data);
+		*status = iic_inb(iic->sts);
+	}
+#endif
+	if (timeout <= 0) {
+		/* Issue stop signal on the bus, and force an interrupt */
+		retval = iic_inb(iic->cntl);
+		iic_outb(iic->cntl, retval | 0x80);
+		/* Clear status register */
+		iic_outb(iic->sts, 0x0a);
+		/* Exit unknown bus state */
+		retval = iic_inb(iic->mdcntl);
+		iic_outb(iic->mdcntl, (retval | 0x02));
+
+		/* Check the status of the controller.  Does it still see a
+		 * pending transfer, even though we've tried to stop any
+		 * ongoing transaction?
+		 */
+		retval = iic_inb(iic->sts);
+		retval = retval & 0x01;
+		if (retval) {
+			/* The iic controller is hosed.  It is not responding to any
+			 * of our commands.  We have already tried to force it into
+			 * a known state, but it has not worked.  Our only choice now
+			 * is a soft reset, which will clear all registers, and force
+			 * us to re-initialize the controller.
+			 * Soft reset
+			 */
+			iic_outb(iic->xtcntlss, 0x01);
+			udelay(500);
+			iic_init(adap);
+			/* Is the pending transfer bit in the sts reg finally cleared? */
+			retval = iic_inb(iic->sts);
+			retval = retval & 0x01;
+			if (retval) {
+				printk(KERN_CRIT
+				       "The IIC Controller is hosed.  A processor reset is required\n");
+			}
+			/* For some reason, even though the interrupt bit in this
+			 * register was set during iic_init, it didn't take.  We
+			 * need to set it again.  Don't ask me why....this is just what
+			 * I saw when testing timeouts.
+			 */
+			iic_outb(iic->intmsk, 0x01);
+		}
+		return (-1);
+	} else
+		return (0);
+}
+
+/* ------------------------------------ */
+/*  Utility functions */
+
+/*  Description: Look at the status register to see if there was an error 
+ *  in the requested transaction.  If there is, look at the extended status 
+ *  register and determine the exact cause. 
+ */
+
+int
+analyze_status(struct i2c_adapter *adap, int *error_code)
+{
+	int ret;
+	struct iic_regs *iic;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	ret = iic_inb(iic->sts);
+	if (ret & 0x04) {
+		/* Error occurred */
+		ret = iic_inb(iic->extsts);
+		if (ret & 0x04) {
+			/* Lost arbitration */
+			*error_code = IIC_ERR_LOST_ARB;
+		}
+		if (ret & 0x02) {
+			/* Incomplete transfer */
+			*error_code = IIC_ERR_INCOMPLETE_XFR;
+		}
+		if (ret & 0x01) {
+			/* Master transfer aborted by a NACK during the transfer of the address byte */
+			*error_code = IIC_ERR_NACK;
+		}
+		return -1;
+	}
+	return 0;
+}
+
+/*  Description: This function is called by the upper layers to do the 
+ *  grunt work for a master send transaction
+ */
+
+static int
+iic_sendbytes(struct i2c_adapter *adap, const char *buf,
+	      int count, int xfer_flag)
+{
+	struct iic_regs *iic;
+	int wrcount, status, timeout;
+	int loops, remainder, i, j;
+	int ret, error_code;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	if (count == 0)
+		return 0;
+	wrcount = 0;
+	loops = count / 4;
+	remainder = count % 4;
+
+	if ((loops > 1) && (remainder == 0)) {
+		for (i = 0; i < (loops - 1); i++) {
+
+			/* Write four bytes to master data buffer */
+
+			for (j = 0; j < 4; j++) {
+				iic_outb(iic->mdbuf, buf[wrcount++]);
+			}
+
+			/* Issue command to IICO device to begin transmission */
+
+			iic_outb(iic->cntl, 0x35);
+
+			/*    Wait for transmission to complete.  When it does,  
+			 *    loop to the top of the for statement and write the  
+			 *    next four bytes. 
+			 */
+
+			timeout = wait_for_pin(adap, &status);
+			if (timeout < 0) {
+
+				/* Error handling */
+
+				return wrcount;
+			}
+			ret = analyze_status(adap, &error_code);
+			if (ret < 0) {
+				if (error_code == IIC_ERR_INCOMPLETE_XFR) {
+					/* Return the number of bytes transferred */
+					ret = iic_inb(iic->xfrcnt);
+					ret = ret & 0x07;
+					return (wrcount - 4 + ret);
+				} else
+					return error_code;
+			}
+		}
+	} else if ((loops >= 1) && (remainder > 0)) {
+		/*printk(KERN_DEBUG "iic_sendbytes: (loops >= 1)\n"); */
+		for (i = 0; i < loops; i++) {
+			/*
+			 * Write four bytes to master data buffer
+			 */
+			for (j = 0; j < 4; j++) {
+				iic_outb(iic->mdbuf, buf[wrcount++]);
+			}
+			/*
+			 * Issue command to IICO device to begin transmission
+			 */
+			iic_outb(iic->cntl, 0x35);
+			/*
+			 * Wait for transmission to complete.  When it does,
+			 * loop to the top of the for statement and write the
+			 * next four bytes.
+			 */
+			timeout = wait_for_pin(adap, &status);
+			if (timeout < 0)
+				return wrcount;
+
+			ret = analyze_status(adap, &error_code);
+			if (ret < 0) {
+				if (error_code == IIC_ERR_INCOMPLETE_XFR) {
+					/* Return the number of bytes transferred */
+					ret = iic_inb(iic->xfrcnt);
+					ret = ret & 0x07;
+					return (wrcount - 4 + ret);
+				} else
+					return error_code;
+			}
+		}
+	}
+
+	if (remainder == 0)
+		remainder = 4;
+	/* Write the remaining bytes (less than or equal to 4) */
+
+	for (i = 0; i < remainder; i++)
+		iic_outb(iic->mdbuf, buf[wrcount++]);
+
+	if (xfer_flag == IIC_COMBINED_XFER) {
+		iic_outb(iic->cntl, (0x09 | ((remainder - 1) << 4)));
+	} else {
+		iic_outb(iic->cntl, (0x01 | ((remainder - 1) << 4)));
+	}
+	DEB2(printk(KERN_DEBUG "iic_sendbytes: Waiting for interrupt\n"));
+	timeout = wait_for_pin(adap, &status);
+	if (timeout < 0)
+		return wrcount;
+	ret = analyze_status(adap, &error_code);
+	if (ret < 0) {
+		if (error_code == IIC_ERR_INCOMPLETE_XFR) {
+			/* Return the number of bytes transferred */
+			ret = iic_inb(iic->xfrcnt);
+			ret = ret & 0x07;
+			return (wrcount - 4 + ret);
+		} else
+			return error_code;
+	}
+	DEB2(printk(KERN_DEBUG "iic_sendbytes: Got interrupt\n"));
+	return wrcount;
+}
+
+/*
+ * Description: Called by the upper layers to do the grunt work for
+ * a master read transaction.
+ */
+static int
+iic_readbytes(struct i2c_adapter *adap, char *buf, int count, int xfer_type)
+{
+	struct iic_regs *iic;
+	int rdcount = 0, i, status, timeout;
+	int loops, remainder, j;
+	int ret, error_code;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	if (count == 0)
+		return 0;
+	loops = count / 4;
+	remainder = count % 4;
+
+	if ((loops > 1) && (remainder == 0)) {
+		for (i = 0; i < (loops - 1); i++) {
+			/* Issue command to begin master read (4 bytes maximum) */
+			iic_outb(iic->cntl, 0x37);
+			/*
+			 * Wait for transmission to complete.  When it does,
+			 * loop to the top of the for statement and write the
+			 * next four bytes.
+			 */
+			timeout = wait_for_pin(adap, &status);
+			if (timeout < 0)
+				return rdcount;
+
+			ret = analyze_status(adap, &error_code);
+			if (ret < 0) {
+				if (error_code == IIC_ERR_INCOMPLETE_XFR)
+					return rdcount;
+				else
+					return error_code;
+			}
+
+			for (j = 0; j < 4; j++) {
+				/* Wait for data to shuffle to top of data buffer
+				 * This value needs to optimized.
+				 */
+				udelay(1);
+				buf[rdcount] = iic_inb(iic->mdbuf);
+				rdcount++;
+			}
+		}
+	}
+
+	else if ((loops >= 1) && (remainder > 0)) {
+		for (i = 0; i < loops; i++) {
+			/* Issue command to begin master read (4 bytes maximum) */
+			iic_outb(iic->cntl, 0x37);
+			/*
+			 * Wait for transmission to complete.  When it does,
+			 * loop to the top of the for statement and write the
+			 * next four bytes.
+			 */
+			timeout = wait_for_pin(adap, &status);
+			if (timeout < 0)
+				return rdcount;
+
+			ret = analyze_status(adap, &error_code);
+			if (ret < 0) {
+				if (error_code == IIC_ERR_INCOMPLETE_XFR)
+					return rdcount;
+				else
+					return error_code;
+			}
+
+			for (j = 0; j < 4; j++) {
+				/* Wait for data to shuffle to top of data buffer
+				 * This value needs to optimized.
+				 */
+				udelay(1);
+				buf[rdcount] = iic_inb(iic->mdbuf);
+				rdcount++;
+			}
+		}
+	}
+
+	if (remainder == 0)
+		remainder = 4;
+	DEB2(printk
+	     (KERN_DEBUG "iic_readbytes: writing %x to IICO_CNTL\n",
+	      (0x03 | ((remainder - 1) << 4))));
+
+	if (xfer_type == IIC_COMBINED_XFER) {
+		iic_outb(iic->cntl, (0x0b | ((remainder - 1) << 4)));
+	} else {
+		iic_outb(iic->cntl, (0x03 | ((remainder - 1) << 4)));
+	}
+	DEB2(printk(KERN_DEBUG "iic_readbytes: Wait for pin\n"));
+	timeout = wait_for_pin(adap, &status);
+	DEB2(printk(KERN_DEBUG "iic_readbytes: Got the interrupt\n"));
+	if (timeout < 0)
+		return rdcount;
+
+	ret = analyze_status(adap, &error_code);
+	if (ret < 0) {
+		if (error_code == IIC_ERR_INCOMPLETE_XFR)
+			return rdcount;
+		else
+			return error_code;
+	}
+
+	for (i = 0; i < remainder; i++) {
+		buf[rdcount] = iic_inb(iic->mdbuf);
+		rdcount++;
+	}
+
+	return rdcount;
+}
+
+/*
+ * Description:  This function implements combined transactions.  Combined
+ * transactions consist of combinations of reading and writing blocks of data.
+ * Each transfer (i.e. a read or a write) is separated by a repeated start
+ * condition.
+ */
+static int
+iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+			 int num)
+{
+	int i;
+	struct i2c_msg *pmsg;
+	int ret;
+
+	DEB2(printk(KERN_DEBUG "Beginning combined transaction\n"));
+	for (i = 0; i < num; i++) {
+		pmsg = &msgs[i];
+		if (pmsg->flags & I2C_M_RD) {
+
+			/* Last read or write segment needs to be terminated with a stop */
+			if (i < num - 1) {
+				DEB2(printk(KERN_DEBUG "This one is a read\n"));
+			} else {
+				DEB2(printk
+				     (KERN_DEBUG "Doing the last read\n"));
+			}
+			ret =
+			    iic_readbytes(i2c_adap, pmsg->buf, pmsg->len,
+					  (i <
+					   num -
+					   1) ? IIC_COMBINED_XFER :
+					  IIC_SINGLE_XFER);
+
+			if (ret != pmsg->len) {
+				DEB2(printk("i2c-algo-ppc405.o: fail: "
+					    "only read %d bytes.\n", ret));
+				return i;
+			} else {
+				DEB2(printk
+				     ("i2c-algo-ppc405.o: read %d bytes.\n",
+				      ret));
+			}
+		} else if (!(pmsg->flags & I2C_M_RD)) {
+
+			/* Last read or write segment needs to be terminated with a stop */
+			if (i < num - 1) {
+				DEB2(printk
+				     (KERN_DEBUG "This one is a write\n"));
+			} else {
+				DEB2(printk
+				     (KERN_DEBUG "Doing the last write\n"));
+			}
+			ret =
+			    iic_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
+					  (i <
+					   num -
+					   1) ? IIC_COMBINED_XFER :
+					  IIC_SINGLE_XFER);
+
+			if (ret != pmsg->len) {
+				DEB2(printk("i2c-algo-ppc405.o: fail: "
+					    "only wrote %d bytes.\n", ret));
+				return i;
+			} else {
+				DEB2(printk
+				     ("i2c-algo-ppc405.o: wrote %d bytes.\n",
+				      ret));
+			}
+		}
+	}
+
+	return num;
+}
+
+/*
+ * Description: Whenever we initiate a transaction, the first byte clocked
+ * onto the bus after the start condition is the address (7 bit) of the
+ * device we want to talk to.  This function manipulates the address specified
+ * so that it makes sense to the hardware when written to the IIC peripheral.
+ *
+ * Note: 10 bit addresses are not supported in this driver, although they are
+ * supported by the hardware.  This functionality needs to be implemented.
+ */
+static inline int
+iic_doAddress(struct i2c_adapter *adap, struct i2c_msg *msg, int retries)
+{
+	struct iic_regs *iic;
+	unsigned short flags = msg->flags;
+	unsigned char addr;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+/*
+ * The following segment for 10 bit addresses needs to be ported
+ */
+#if 0
+	/* Ten bit addresses not supported right now */
+	if ((flags & I2C_M_TEN)) {
+		/* a ten bit address */
+		addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+		DEB2(printk(KERN_DEBUG "addr0: %d\n", addr));
+		/* try extended address code... */
+		ret = try_address(adap, addr, retries);
+		if (ret != 1) {
+			printk(KERN_ERR
+			       "iic_doAddress: died at extended address code.\n");
+			return -EREMOTEIO;
+		}
+		/* the remaining 8 bit address */
+		iic_outb(msg->addr & 0x7f);
+		/* Status check comes here */
+		if (ret != 1) {
+			printk(KERN_ERR
+			       "iic_doAddress: died at 2nd address code.\n");
+			return -EREMOTEIO;
+		}
+		if (flags & I2C_M_RD) {
+			i2c_repstart(adap);
+			/* okay, now switch into reading mode */
+			addr |= 0x01;
+			ret = try_address(adap, addr, retries);
+			if (ret != 1) {
+				printk(KERN_ERR
+				       "iic_doAddress: died at extended address code.\n");
+				return -EREMOTEIO;
+			}
+		}
+	} else
+		/* ---------->  normal 7 bit address */
+		/*Ten bit addresses not supported yet */
+#endif
+		addr = (msg->addr << 1);
+	if (flags & I2C_M_RD)
+		addr |= 1;
+	if (flags & I2C_M_REV_DIR_ADDR)
+		addr ^= 1;
+	/*
+	 * Write to the low slave address
+	 */
+	iic_outb(iic->lmadr, addr);
+	/*
+	 * Write zero to the high slave register since we are
+	 * only using 7 bit addresses
+	 */
+	iic_outb(iic->hmadr, 0);
+
+	return 0;
+}
+
+/*
+ * Description: Prepares the controller for a transaction (clearing status
+ * registers, data buffers, etc), and then calls either iic_readbytes or
+ * iic_sendbytes to do the actual transaction.
+ */
+static int
+iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct iic_regs *iic;
+	struct i2c_msg *pmsg;
+	int i = 0;
+	int ret;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	pmsg = &msgs[i];
+
+	/*
+	 * Clear status register
+	 */
+	DEB2(printk
+	     (KERN_DEBUG "iic_xfer: iic_xfer: Clearing status register\n"));
+	iic_outb(iic->sts, 0x0a);
+
+	/*
+	 * Wait for any pending transfers to complete
+	 */
+	DEB2(printk
+	     (KERN_DEBUG
+	      "iic_xfer: Waiting for any pending transfers to complete\n"));
+	while ((ret = iic_inb(iic->sts)) == 0x01) {
+		;
+	}
+
+	/*
+	 * Flush master data buf
+	 */
+	DEB2(printk(KERN_DEBUG "iic_xfer: Clearing master data buffer\n"));
+	ret = iic_inb(iic->mdcntl);
+	iic_outb(iic->mdcntl, ret | 0x40);
+
+	/*
+	 * Load slave address
+	 */
+	DEB2(printk(KERN_DEBUG "iic_xfer: Loading slave address\n"));
+	ret = iic_doAddress(adap, pmsg, adap->retries);
+	/*
+	 * Check to see if the bus is busy
+	 */
+	ret = iic_inb(iic->extsts);
+	/* Mask off the irrelevent bits */
+	ret = ret & 0x70;
+	/* When the bus is free, the BCS bits in the EXTSTS register are 0b100 */
+	if (ret != 0x40)
+		return IIC_ERR_LOST_ARB;
+	/*
+	 * Combined transaction (read and write)
+	 */
+	if (num > 1) {
+		DEB2(printk
+		     (KERN_DEBUG "iic_xfer: Call combined transaction\n"));
+		ret = iic_combined_transaction(adap, msgs, num);
+	}
+	/*
+	 * Read only
+	 */
+	else if ((num == 1) && (pmsg->flags & I2C_M_RD)) {
+		/*
+		 * Tell device to begin reading data from the  master data 
+		 */
+		DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's read\n"));
+		ret =
+		    iic_readbytes(adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
+		ret = (ret == pmsg->len)? num: ret;
+	}
+	/*
+	 * Write only
+	 */
+	else if ((num == 1) && (!(pmsg->flags & I2C_M_RD))) {
+		/*
+		 * Write data to master data buffers and tell our device
+		 * to begin transmitting
+		 */
+		DEB2(printk(KERN_DEBUG "iic_xfer: Call adapter's write\n"));
+		ret =
+		    iic_sendbytes(adap, pmsg->buf, pmsg->len, IIC_SINGLE_XFER);
+		ret = (ret == pmsg->len)? num: ret;
+	}
+
+	return ret;
+}
+
+/*
+ * Description: Implements device specific ioctls.  Higher level ioctls can
+ * be found in i2c-core.c and are typical of any i2c controller (specifying
+ * slave address, timeouts, etc).  These ioctls take advantage of any hardware
+ * features built into the controller for which this algorithm-adapter set
+ * was written.  These ioctls allow you to take control of the data and clock
+ * lines on the IBM PPC 405 IIC controller and set the either high or low,
+ * similar to a GPIO pin.
+ */
+static int
+algo_control(struct i2c_adapter *adap, unsigned int cmd, unsigned long arg)
+{
+	struct iic_regs *iic;
+	int ret = 0;
+	int lines;
+
+	iic = (struct iic_regs *) IIC_DEV(vaddr);
+
+	lines = iic_inb(iic->directcntl);
+
+	if (cmd == IICO_I2C_SDAHIGH) {
+		lines = lines & 0x01;
+		if (lines)
+			lines = 0x04;
+		else
+			lines = 0;
+		iic_outb(iic->directcntl, (0x08 | lines));
+	} else if (cmd == IICO_I2C_SDALOW) {
+		lines = lines & 0x01;
+		if (lines)
+			lines = 0x04;
+		else
+			lines = 0;
+		iic_outb(iic->directcntl, (0x00 | lines));
+	} else if (cmd == IICO_I2C_SCLHIGH) {
+		lines = lines & 0x02;
+		if (lines)
+			lines = 0x08;
+		else
+			lines = 0;
+		iic_outb(iic->directcntl, (0x04 | lines));
+	} else if (cmd == IICO_I2C_SCLLOW) {
+		lines = lines & 0x02;
+		if (lines)
+			lines = 0x08;
+		else
+			lines = 0;
+		iic_outb(iic->directcntl, (0x00 | lines));
+	} else if (cmd == IICO_I2C_LINEREAD) {
+		ret = lines;
+	}
+	return ret;
+}
+
+static u32
+iic_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
+	    I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+/* -----exported algorithm data: -------------------------------------	*/
+
+static struct i2c_algorithm iic_algo = {
+	"IBM on-chip IIC algorithm",
+	I2C_ALGO_OCP,
+	iic_xfer,
+	NULL,
+	NULL,			/* slave_xmit           */
+	NULL,			/* slave_recv           */
+	algo_control,		/* ioctl                */
+	iic_func,		/* functionality        */
+};
+
+/* 
+ * registering functions to load algorithms at runtime 
+ */
+
+/*
+ * Description: Register bus structure
+ */
+int
+i2c_iic_add_bus(struct i2c_adapter *adap)
+{
+
+	DEB2(printk
+	     (KERN_DEBUG "i2c-algo-iic.o: hw routines for %s registered.\n",
+	      adap->name));
+	adap->id |= iic_algo.id;
+	adap->algo = &iic_algo;
+	adap->timeout = IIC_TIMEOUT;
+	adap->retries = IIC_RETRY;
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+
+	iic_init(adap);
+	i2c_add_adapter(adap);
+	/* scan the I2C bus for valid 7 bit addresses
+	 * (ie things that ACK on 1byte read)
+	 * if i2c_debug is off we print everything on one line.
+	 * if i2c_debug is on we do a newline per print so we don't
+	 * clash too much with printk's in the other functions.
+	 * TODO: check for 10-bit mode and never run as a slave.
+	 */
+
+	if (iic_scan) {
+
+		int found = 0;
+		int i;
+		printk(KERN_INFO " i2c-algo-iic.o: scanning bus %s. Found ",
+		       adap->name);
+		if (i2c_debug)
+			printk("\n");
+		for (i = 0; i < 0x7f; i++) {
+			int ret;
+			struct i2c_msg msg;
+			char data[1];
+			msg.addr = i;
+			msg.buf = data;
+			msg.len = 1;
+			msg.flags = I2C_M_RD;
+			if ((ret = iic_xfer(adap, &msg, 1)) == 1) {
+				if (i2c_debug)
+					printk
+					    ("I2C Found 0x%02x ret %d Data 0x%02x\n",
+					     i, ret, data[0]);
+				else
+					printk("0x%02x ", i);
+				found++;
+			}
+		}
+		if (i2c_debug) {
+			if (!found)
+				printk("I2C Found Nothing\n");
+		} else {
+			if (found)
+				printk("\n");
+			else
+				printk("Nothing\n");
+		}
+
+	}
+	return 1;
+}
+
+int
+i2c_iic_del_bus(struct i2c_adapter *adap)
+{
+	int res;
+	if ((res = i2c_del_adapter(adap)) < 0)
+		return res;
+	DEB2(printk
+	     (KERN_DEBUG "i2c-algo-iic.o: adapter unregistered: %s\n",
+	      adap->name));
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	return 1;
+}
+
+int __init
+i2c_algo_iic_init(void)
+{
+	printk(KERN_INFO "IBM On-chip iic (i2c) algorithm module %s\n",
+	       IIC_VER);
+
+	return 0;
+}
+
+void
+i2c_algo_iic_exit(void)
+{
+	return;
+}
+
+EXPORT_SYMBOL(i2c_iic_add_bus);
+EXPORT_SYMBOL(i2c_iic_del_bus);
+
+/*
+ * The MODULE_* macros resolve to nothing if MODULES is not defined
+ * when this file is compiled.
+ */
+MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
+MODULE_DESCRIPTION("PPC 405 iic algorithm");
+
+MODULE_PARM(iic_scan, "i");
+MODULE_PARM(i2c_debug, "i");
+
+MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus");
+MODULE_PARM_DESC(i2c_debug,
+		 "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
+
+MODULE_LICENSE("GPL");
+
+module_init(i2c_algo_iic_init);
+module_exit(i2c_algo_iic_exit);
diff -Naur linux-2.6.0-test10/drivers/i2c/i2c-core.c linux-2.6.0-test10-obs266/drivers/i2c/i2c-core.c
--- linux-2.6.0-test10/drivers/i2c/i2c-core.c	Mon Nov 24 10:31:13 2003
+++ linux-2.6.0-test10-obs266/drivers/i2c/i2c-core.c	Thu Nov 27 03:14:59 2003
@@ -378,6 +378,8 @@
 	if (client->flags & I2C_CLIENT_ALLOW_USE)
 		client->usage_count = 0;
 
+// FIXME for OBS266
+#if 0
 	client->dev.parent = &client->adapter->dev;
 	client->dev.driver = &client->driver->driver;
 	client->dev.bus = &i2c_bus_type;
@@ -388,6 +390,7 @@
 	printk("registering %s\n", client->dev.bus_id);
 	device_register(&client->dev);
 	device_create_file(&client->dev, &dev_attr_client_name);
+#endif
 	
 	return 0;
 }
diff -Naur linux-2.6.0-test10/drivers/ide/hpt366.c linux-2.6.0-test10-obs266/drivers/ide/hpt366.c
--- linux-2.6.0-test10/drivers/ide/hpt366.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/ide/hpt366.c	Wed Nov 26 18:22:49 2003
@@ -0,0 +1,1650 @@
+/*
+ * linux/drivers/ide/hpt366.c		Version 0.22	20 Sep 2001
+ *
+ * Copyright (C) 1999-2000		Andre Hedrick <andre@linux-ide.org>
+ * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ * Thanks to HighPoint Technologies for their assistance, and hardware.
+ * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
+ * donation of an ABit BP6 mainboard, processor, and memory acellerated
+ * development and support.
+ *
+ * Note that final HPT370 support was done by force extraction of GPL.
+ *
+ * - add function for getting/setting power status of drive
+ * - the HPT370's state machine can get confused. reset it before each dma 
+ *   xfer to prevent that from happening.
+ * - reset state engine whenever we get an error.
+ * - check for busmaster state at end of dma. 
+ * - use new highpoint timings.
+ * - detect bus speed using highpoint register.
+ * - use pll if we don't have a clock table. added a 66MHz table that's
+ *   just 2x the 33MHz table.
+ * - removed turnaround. NOTE: we never want to switch between pll and
+ *   pci clocks as the chip can glitch in those cases. the highpoint
+ *   approved workaround slows everything down too much to be useful. in
+ *   addition, we would have to serialize access to each chip.
+ * 	Adrian Sun <a.sun@sun.com>
+ *
+ * add drive timings for 66MHz PCI bus,
+ * fix ATA Cable signal detection, fix incorrect /proc info
+ * add /proc display for per-drive PIO/DMA/UDMA mode and
+ * per-channel ATA-33/66 Cable detect.
+ * 	Duncan Laurie <void@sun.com>
+ *
+ * fixup /proc output for multiple controllers
+ *	Tim Hockin <thockin@sun.com>
+ *
+ * On hpt366: 
+ * Reset the hpt366 on error, reset on dma
+ * Fix disabling Fast Interrupt hpt366.
+ * 	Mike Waychison <crlf@sun.com>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_HPT366_TIMINGS
+
+/* various tuning parameters */
+#define HPT_RESET_STATE_ENGINE
+/*#define HPT_DELAY_INTERRUPT*/
+/*#define HPT_SERIALIZE_IO*/
+
+#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static unsigned int hpt_revision(struct pci_dev *dev);
+static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision);
+
+extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+
+const char *quirk_drives[] = {
+	"QUANTUM FIREBALLlct08 08",
+	"QUANTUM FIREBALLP KA6.4",
+	"QUANTUM FIREBALLP LM20.4",
+	"QUANTUM FIREBALLP LM20.5",
+        NULL
+};
+
+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
+};
+
+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
+};
+
+const char *bad_ata66_3[] = {
+	"WDC AC310200R",
+	NULL
+};
+
+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
+};
+
+struct chipset_bus_clock_list_entry {
+	byte		xfer_speed;
+	unsigned int	chipset_settings;
+};
+
+/* from linux-2.5.63/drivers/ide/pci/hpt366.h */
+/* 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.
+ */
+struct chipset_bus_clock_list_entry forty_base_hpt366[] = {
+	{	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	}
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = {
+	{	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	}
+};
+
+struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = {
+
+	{	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	}
+};
+
+/* from highpoint documentation. these are old values */
+struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = {
+/*	{	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	}
+};
+
+struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = {
+	{       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 */
+struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = {
+        {       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 */
+struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = {
+	{       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       }
+};
+
+struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = {
+	{       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      }
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = {
+	{	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	}
+};
+
+struct chipset_bus_clock_list_entry fifty_base_hpt372[] = {
+	{	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	}
+};
+
+struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = {
+	{	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	}
+};
+
+struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = {
+	{	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	}
+};
+
+#if 0
+struct chipset_bus_clock_list_entry fifty_base_hpt374[] = {
+	{	XFER_UDMA_6,	},
+	{	XFER_UDMA_5,	},
+	{	XFER_UDMA_4,	},
+	{	XFER_UDMA_3,	},
+	{	XFER_UDMA_2,	},
+	{	XFER_UDMA_1,	},
+	{	XFER_UDMA_0,	},
+	{	XFER_MW_DMA_2,	},
+	{	XFER_MW_DMA_1,	},
+	{	XFER_MW_DMA_0,	},
+	{	XFER_PIO_4,	},
+	{	XFER_PIO_3,	},
+	{	XFER_PIO_2,	},
+	{	XFER_PIO_1,	},
+	{	XFER_PIO_0,	},
+	{	0,	}
+};
+#endif
+#if 0
+struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = {
+	{	XFER_UDMA_6,	0x12406231	},	/* checkme */
+	{	XFER_UDMA_5,	0x12446231	},
+				0x14846231
+	{	XFER_UDMA_4,		0x16814ea7	},
+				0x14886231
+	{	XFER_UDMA_3,		0x16814ea7	},
+				0x148c6231
+	{	XFER_UDMA_2,		0x16814ea7	},
+				0x148c6231
+	{	XFER_UDMA_1,		0x16814ea7	},
+				0x14906231
+	{	XFER_UDMA_0,		0x16814ea7	},
+				0x14986231
+	{	XFER_MW_DMA_2,		0x16814ea7	},
+				0x26514e21
+	{	XFER_MW_DMA_1,		0x16814ea7	},
+				0x26514e97
+	{	XFER_MW_DMA_0,		0x16814ea7	},
+				0x26514e97
+	{	XFER_PIO_4,		0x06814ea7	},
+				0x06514e21
+	{	XFER_PIO_3,		0x06814ea7	},
+				0x06514e22
+	{	XFER_PIO_2,		0x06814ea7	},
+				0x06514e33
+	{	XFER_PIO_1,		0x06814ea7	},
+				0x06914e43
+	{	XFER_PIO_0,		0x06814ea7	},
+				0x06914e57
+	{	0,		0x06814ea7	}
+};
+#endif
+
+#define HPT366_DEBUG_DRIVE_INFO		0
+#define HPT374_ALLOW_ATA133_6		0
+#define HPT371_ALLOW_ATA133_6		0
+#define HPT302_ALLOW_ATA133_6		0
+#define HPT372_ALLOW_ATA133_6		1
+#define HPT370_ALLOW_ATA100_5		1
+#define HPT366_ALLOW_ATA66_4		1
+#define HPT366_ALLOW_ATA66_3		1
+#define HPT366_MAX_DEVS			8
+
+#define F_LOW_PCI_33      0x23
+#define F_LOW_PCI_40      0x29
+#define F_LOW_PCI_50      0x2d
+#define F_LOW_PCI_66      0x42
+
+static struct pci_dev *hpt_devs[HPT366_MAX_DEVS];
+static int n_hpt_devs;
+
+byte hpt366_proc = 0;
+byte hpt363_shared_irq;
+byte hpt363_shared_pin;
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static int hpt37x_ide_dma_check_done=0;
+
+#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
+static int hpt366_get_info(char *, char **, off_t, int);
+extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+
+static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+	char *p	= buffer;
+	char *chipset_nums[] = {"366", "366", "368", "370", "370A",
+				"372", "302", "371",  "374" };
+	int i;
+
+	p += sprintf(p, "\n                             "
+		     "HighPoint HPT366/368/370/371\n");
+	for (i = 0; i < n_hpt_devs; i++) {
+		struct pci_dev *dev = hpt_devs[i];
+		unsigned long iobase = dev->resource[4].start;
+		u32 class_rev = hpt_revision(dev);
+		u8 c0, c1;
+
+		p += sprintf(p, "\nController: %d\n", i);
+
+		p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);
+		p += sprintf(p, "--------------- Primary Channel "
+				"--------------- Secondary Channel "
+				"--------------\n");
+
+		/* get the bus master status registers */
+		c0 = inb_p(iobase + 0x2);
+		c1 = inb_p(iobase + 0xa);
+		p += sprintf(p, "Enabled:        %s"
+				"                             %s\n",
+			(c0 & 0x80) ? "no" : "yes",
+			(c1 & 0x80) ? "no" : "yes");
+
+#ifdef NEVER
+		if (hpt_minimum_revision(dev, 3)) {
+			u8 cbl;
+			cbl = inb_p(iobase + 0x7b);
+			outb_p(cbl | 1, iobase + 0x7b);
+			outb_p(cbl & ~1, iobase + 0x7b);
+			cbl = inb_p(iobase + 0x7a);
+			p += sprintf(p, "Cable:          ATA-%d"
+					"                          ATA-%d\n",
+				(cbl & 0x02) ? 33 : 66,
+				(cbl & 0x01) ? 33 : 66);
+			p += sprintf(p, "\n");
+		}
+#endif
+
+		p += sprintf(p, "--------------- drive0 --------- drive1 "
+				"------- drive0 ---------- drive1 -------\n");
+		p += sprintf(p, "DMA capable:    %s              %s" 
+				"            %s               %s\n",
+			(c0 & 0x20) ? "yes" : "no ", 
+			(c0 & 0x40) ? "yes" : "no ",
+			(c1 & 0x20) ? "yes" : "no ", 
+			(c1 & 0x40) ? "yes" : "no ");
+
+		{
+			u8 c2, c3;
+			/* older revs don't have these registers mapped 
+			 * into io space */
+			pci_read_config_byte(dev, 0x43, &c0);
+			pci_read_config_byte(dev, 0x47, &c1);
+			pci_read_config_byte(dev, 0x4b, &c2);
+			pci_read_config_byte(dev, 0x4f, &c3);
+
+			p += sprintf(p, "Mode:           %s             %s"
+					"           %s              %s\n",
+				(c0 & 0x10) ? "UDMA" : (c0 & 0x20) ? "DMA " : 
+					(c0 & 0x80) ? "PIO " : "off ",
+				(c1 & 0x10) ? "UDMA" : (c1 & 0x20) ? "DMA " :
+					(c1 & 0x80) ? "PIO " : "off ",
+				(c2 & 0x10) ? "UDMA" : (c2 & 0x20) ? "DMA " :
+					(c2 & 0x80) ? "PIO " : "off ",
+				(c3 & 0x10) ? "UDMA" : (c3 & 0x20) ? "DMA " :
+					(c3 & 0x80) ? "PIO " : "off ");
+		}
+	}
+	p += sprintf(p, "\n");
+	
+	return p-buffer;/* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+static u32 hpt_revision (struct pci_dev *dev)
+{
+	u32 class_rev;
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	switch(dev->device) {
+		case PCI_DEVICE_ID_TTI_HPT374:
+			class_rev = PCI_DEVICE_ID_TTI_HPT374; break;
+		case PCI_DEVICE_ID_TTI_HPT371:
+			class_rev = PCI_DEVICE_ID_TTI_HPT371; break;
+		case PCI_DEVICE_ID_TTI_HPT302:
+			class_rev = PCI_DEVICE_ID_TTI_HPT302; break;
+		case PCI_DEVICE_ID_TTI_HPT372:
+			class_rev = PCI_DEVICE_ID_TTI_HPT372; break;
+		default:
+			break;
+	}
+	return class_rev;
+}
+
+static u32 hpt_minimum_revision (struct pci_dev *dev, int revision)
+{
+	unsigned int class_rev = hpt_revision(dev);
+	revision--;
+	return ((int) (class_rev > revision) ? 1 : 0);
+}
+
+static int check_in_drive_lists(ide_drive_t *drive, const char **list);
+
+static u8 hpt3xx_ratemask (ide_drive_t *drive)
+{
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	u8 mode			= 0;
+
+	if (hpt_minimum_revision(dev, 8)) {		/* HPT374 */
+		mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3;
+	} else if (hpt_minimum_revision(dev, 7)) {	/* HPT371 */
+		mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3;
+	} else if (hpt_minimum_revision(dev, 6)) {	/* HPT302 */
+		mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3;
+	} else if (hpt_minimum_revision(dev, 5)) {	/* HPT372 */
+		mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3;
+	} else if (hpt_minimum_revision(dev, 4)) {	/* HPT370A */
+		mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
+	} else if (hpt_minimum_revision(dev, 3)) {	/* HPT370 */
+		mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2;
+		mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode;
+	} else {				/* HPT366 and HPT368 */
+		mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2;
+	}
+	if (!eighty_ninty_three(drive) && (mode))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed)
+{
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	u8 mode			= hpt3xx_ratemask(drive);
+
+	if (drive->media != ide_disk)
+		return min(speed, (u8)XFER_PIO_4);
+
+	switch(mode) {
+		case 0x04:
+			speed = min(speed, (u8)XFER_UDMA_6);
+			break;
+		case 0x03:
+			speed = min(speed, (u8)XFER_UDMA_5);
+			if (hpt_minimum_revision(dev, 5))
+				break;
+			if (check_in_drive_lists(drive, bad_ata100_5))
+				speed = min(speed, (u8)XFER_UDMA_4);
+			break;
+		case 0x02:
+			speed = min(speed, (u8)XFER_UDMA_4);
+	/*
+	 * CHECK ME, Does this need to be set to 5 ??
+	 */
+			if (hpt_minimum_revision(dev, 3))
+				break;
+			if ((check_in_drive_lists(drive, bad_ata66_4)) ||
+			    (!(HPT366_ALLOW_ATA66_4)))
+				speed = min(speed, (u8)XFER_UDMA_3);
+			if ((check_in_drive_lists(drive, bad_ata66_3)) ||
+			    (!(HPT366_ALLOW_ATA66_3)))
+				speed = min(speed, (u8)XFER_UDMA_2);
+			break;
+		case 0x01:
+			speed = min(speed, (u8)XFER_UDMA_2);
+	/*
+	 * CHECK ME, Does this need to be set to 5 ??
+	 */
+			if (hpt_minimum_revision(dev, 3))
+				break;
+			if (check_in_drive_lists(drive, bad_ata33))
+				speed = min(speed, (u8)XFER_MW_DMA_2);
+			break;
+		case 0x00:
+		default:
+			speed = min(speed, (u8)XFER_MW_DMA_2);
+			break;
+	}
+	return speed;
+}
+
+static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+{
+	struct hd_driveid *id = drive->id;
+
+	if (quirk_drives == list) {
+		while (*list) {
+			if (strstr(id->model, *list++)) {
+				return 1;
+			}
+		}
+	} else {
+		while (*list) {
+			if (!strcmp(*list++,id->model)) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+	for ( ; chipset_table->xfer_speed ; chipset_table++)
+		if (chipset_table->xfer_speed == speed) {
+			return chipset_table->chipset_settings;
+		}
+	return chipset_table->chipset_settings;
+}
+
+static void hpt366_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	byte regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
+	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+			/*
+			 * since the channel is always 0 it does not matter.
+			 */
+
+	unsigned int reg1	= 0;
+	unsigned int reg2	= 0;
+	byte drive_fast		= 0;
+
+	/*
+	 * Disable the "fast interrupt" prediction. 
+	 */
+	pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast);
+	if (drive_fast & 0x80)
+		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x80);
+
+	pci_read_config_dword(HWIF(drive)->pci_dev, regtime, &reg1);
+	/* detect bus speed by looking at control reg timing: */
+	switch((reg1 >> 8) & 7) {
+		case 5:
+			reg2 = pci_bus_clock_list(speed, forty_base_hpt366);
+			break;
+		case 9:
+			reg2 = pci_bus_clock_list(speed, twenty_five_base_hpt366);
+			break;
+		default:
+		case 7:
+			reg2 = pci_bus_clock_list(speed, thirty_three_base_hpt366);
+			break;
+	}
+#if 0
+	/* this is a nice idea ... */
+	list_conf = pci_bus_clock_list(speed,
+				       (struct chipset_bus_clock_list_entry *)
+				       pci_get_drvdata(dev));
+#endif
+	/*
+	 * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later)
+	 */
+	if (speed >= XFER_MW_DMA_0) {
+		reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);
+	} else {
+		reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
+	}	
+	reg2 &= ~0x80000000;
+
+	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
+}
+
+static void hpt368_tune_chipset (ide_drive_t *drive, u8 speed)
+{
+	hpt366_tune_chipset(drive, speed);
+}
+
+static void hpt370_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	byte regfast		= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	unsigned int list_conf	= 0;
+	unsigned int drive_conf = 0;
+	unsigned int conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
+	byte drive_pci		= 0x40 + (drive->dn * 4);
+	byte new_fast, drive_fast		= 0;
+	struct pci_dev *dev 	= HWIF(drive)->pci_dev;
+
+	printk("HPT366: use old code -- fix me\n");
+	/*
+	 * Disable the "fast interrupt" prediction.
+	 * don't holdoff on interrupts. (== 0x01 despite what the docs say) 
+	 */
+	pci_read_config_byte(dev, regfast, &drive_fast);
+	new_fast = drive_fast;
+	if (new_fast & 0x02)
+		new_fast &= ~0x02;
+
+#ifdef HPT_DELAY_INTERRUPT
+	if (new_fast & 0x01)
+		new_fast &= ~0x01;
+#else
+	if ((new_fast & 0x01) == 0)
+		new_fast |= 0x01;
+#endif
+	if (new_fast != drive_fast)
+		pci_write_config_byte(HWIF(drive)->pci_dev, regfast, new_fast);
+
+	list_conf = pci_bus_clock_list(speed, 
+				       (struct chipset_bus_clock_list_entry *)
+				       pci_get_drvdata(dev));
+
+	pci_read_config_dword(dev, drive_pci, &drive_conf);
+	list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
+	
+	if (speed < XFER_MW_DMA_0) {
+		list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+	}
+
+	pci_write_config_dword(dev, drive_pci, list_conf);
+}
+
+static void hpt372_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+{
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+	u8 speed	= hpt3xx_ratefilter(drive, xferspeed);
+//	u8 speed	= ide_rate_filter(hpt3xx_ratemask(drive), xferspeed);
+	u8 regfast	= (HWIF(drive)->channel) ? 0x55 : 0x51;
+	u8 drive_fast	= 0, drive_pci = 0x40 + (drive->dn * 4);
+	u32 list_conf	= 0, drive_conf = 0;
+	u32 conf_mask	= (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
+
+	/*
+	 * Disable the "fast interrupt" prediction.
+	 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
+	 */
+	pci_read_config_byte(dev, regfast, &drive_fast);
+	drive_fast &= ~0x07;
+	pci_write_config_byte(dev, regfast, drive_fast);
+					
+	list_conf = pci_bus_clock_list(speed,
+			(struct chipset_bus_clock_list_entry *)
+					pci_get_drvdata(dev));
+	pci_read_config_dword(dev, drive_pci, &drive_conf);
+	list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
+	if (speed < XFER_MW_DMA_0)
+		list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+	pci_write_config_dword(dev, drive_pci, list_conf);
+}
+
+static void hpt374_tune_chipset (ide_drive_t *drive, u8 speed)
+{
+	hpt372_tune_chipset(drive, speed);
+}
+
+static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+
+	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))
+		return -1;
+
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
+	if (hpt_minimum_revision(dev, 8))
+		hpt374_tune_chipset(drive, speed);
+#if 0
+	else if (hpt_minimum_revision(dev, 7))
+		hpt371_tune_chipset(drive, speed);
+	else if (hpt_minimum_revision(dev, 6))
+		hpt302_tune_chipset(drive, speed);
+#endif
+	else if (hpt_minimum_revision(dev, 5))
+		hpt372_tune_chipset(drive, speed);
+	else if (hpt_minimum_revision(dev, 3))
+		hpt370_tune_chipset(drive, speed);
+	else if (hpt_minimum_revision(dev, 2))
+		hpt368_tune_chipset(drive, speed);
+	else
+                hpt366_tune_chipset(drive, speed);
+	drive->current_speed = speed;
+	return ((int) ide_config_drive_speed(drive, speed));
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+	unsigned short xfer_pio = drive->id->eide_pio_modes;
+	byte	timing, speed, pio;
+
+	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+	if (xfer_pio> 4)
+		xfer_pio = 0;
+
+	if (drive->id->eide_pio_iordy > 0) {
+		for (xfer_pio = 5;
+			xfer_pio>0 &&
+			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+			xfer_pio--);
+	} else {
+		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+			   (drive->id->eide_pio_modes & 2) ? 0x04 :
+			   (drive->id->eide_pio_modes & 1) ? 0x03 :
+			   (drive->id->tPIO & 2) ? 0x02 :
+			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+	switch(timing) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+	(void) hpt3xx_tune_chipset(drive, speed);
+}
+
+static void hpt3xx_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+	switch(pio) {
+		case 4:		speed = XFER_PIO_4;break;
+		case 3:		speed = XFER_PIO_3;break;
+		case 2:		speed = XFER_PIO_2;break;
+		case 1:		speed = XFER_PIO_1;break;
+		default:	speed = XFER_PIO_0;break;
+	}
+
+	/* no check a range of pio -- fix me */
+
+	(void) hpt3xx_tune_chipset(drive, speed);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.  Initally for designed for
+ * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
+ *
+ * check_in_drive_lists(drive, bad_ata66_4)
+ * check_in_drive_lists(drive, bad_ata66_3)
+ * check_in_drive_lists(drive, bad_ata33)
+ *
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	byte speed		= 0x00;
+	byte ultra66		= eighty_ninty_three(drive);
+	byte mode		= hpt3xx_ratemask(drive);
+	int  rval;
+
+	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))
+		return ((int) ide_dma_off_quietly);
+
+	if ((id->dma_ultra & 0x0040) &&
+	    (HPT370_ALLOW_ATA100_5)  &&
+	    (mode >= 0x04) &&
+	    (ultra66)) {
+		speed = XFER_UDMA_6;
+	} else if ((id->dma_ultra & 0x0020) &&
+	    (!check_in_drive_lists(drive, bad_ata100_5)) &&
+	    (HPT370_ALLOW_ATA100_5) &&
+	    (mode >= 0x03) &&
+	    (ultra66)) {
+		speed = XFER_UDMA_5;
+	} else if ((id->dma_ultra & 0x0010) &&
+		   (!check_in_drive_lists(drive, bad_ata66_4)) &&
+		   (mode >= 0x02) &&
+		   (ultra66)) {
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) &&
+		   (!check_in_drive_lists(drive, bad_ata66_3)) &&
+		   (mode >= 0x02) &&
+		   (ultra66)) {
+		speed = XFER_UDMA_3;
+	} else if (id->dma_ultra &&
+		   (mode >= 0x01) &&
+		   (!check_in_drive_lists(drive, bad_ata33))) {
+		if (id->dma_ultra & 0x0004) {
+			speed = XFER_UDMA_2;
+		} else if (id->dma_ultra & 0x0002) {
+			speed = XFER_UDMA_1;
+		} else if (id->dma_ultra & 0x0001) {
+			speed = XFER_UDMA_0;
+		}
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		speed = XFER_MW_DMA_0;
+	} else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) hpt3xx_tune_chipset(drive, speed);
+
+	rval = (int)(	((id->dma_ultra >> 11) & 7) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+	return rval;
+}
+
+int hpt3xx_quirkproc (ide_drive_t *drive)
+{
+	return ((int) check_in_drive_lists(drive, quirk_drives));
+}
+
+void hpt3xx_intrproc (ide_drive_t *drive)
+{
+	if (drive->quirk_list) {
+		/* drives in the quirk_list may not like intr setups/cleanups */
+	} else {
+		OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+	}
+}
+
+void hpt3xx_maskproc (ide_drive_t *drive, int mask)
+{
+	if (drive->quirk_list) {
+		if (hpt_minimum_revision(HWIF(drive)->pci_dev,3)) {
+			byte reg5a = 0;
+			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5a);
+			if (((reg5a & 0x10) >> 4) != mask)
+				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
+		} else {
+			if (mask) {
+				disable_irq(HWIF(drive)->irq);
+			} else {
+				enable_irq(HWIF(drive)->irq);
+			}
+		}
+	} else {
+		if (IDE_CONTROL_REG)
+			OUT_BYTE(mask ? (drive->ctl | 2) : (drive->ctl & ~2), IDE_CONTROL_REG);
+	}
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		hpt37x_ide_dma_check_done = 1;
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x002F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if (id->dma_mword & 0x0007) {  /* xxx */
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ( (id && (id->capability & 8)) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+		config_chipset_for_pio(drive);
+	} else {
+		if( !(id && (id->capability & 1)) ){
+			printk("HPT37X: %s: unsupported DMA drive\n", drive->name);
+			return 1;
+		}
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ *
+ * This is specific to the HPT366 UDMA bios chipset
+ * by HighPoint|Triones Technologies, Inc.
+ */
+int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0;
+	unsigned long dma_base = HWIF(drive)->dma_base;
+
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */
+			dma_stat = inb(dma_base+2);
+			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
+		case ide_dma_lostirq:
+			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
+			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+			pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, &reg5ah);
+			printk("%s: (%s)  reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
+				drive->name,
+				ide_dmafunc_verbose(func),
+				reg50h, reg52h, reg5ah);
+			if (reg5ah & 0x10)
+				pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10);
+			/* fall through to a reset */
+#if 0
+		case ide_dma_begin:
+		case ide_dma_end:
+			/* reset the chips state over and over.. */
+			pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13);
+#endif
+			break;
+		case ide_dma_timeout:
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte regstate = hwif->channel ? 0x54 : 0x50;
+	byte reginfo = hwif->channel ? 0x56 : 0x52;
+	byte dma_stat;
+
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_test_irq:	/* returns 1 if dma irq issued, 0 otherwise */
+			dma_stat = inb(dma_base+2);
+			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
+
+		case ide_dma_end:
+			dma_stat = inb(dma_base + 2);
+			if (dma_stat & 0x01) {
+				udelay(20); /* wait a little */
+				dma_stat = inb(dma_base + 2);
+			}
+			if ((dma_stat & 0x01) == 0) 
+				break;
+
+			func = ide_dma_timeout;
+			/* fallthrough */
+
+		case ide_dma_timeout:
+		case ide_dma_lostirq:
+			pci_read_config_byte(hwif->pci_dev, reginfo, 
+					     &dma_stat); 
+			printk("%s: %d bytes in FIFO\n", drive->name, 
+			       dma_stat);
+			pci_write_config_byte(hwif->pci_dev, regstate, 0x37);
+			udelay(10);
+			dma_stat = inb(dma_base);
+			outb(dma_stat & ~0x1, dma_base); /* stop dma */
+			dma_stat = inb(dma_base + 2); 
+			outb(dma_stat | 0x6, dma_base+2); /* clear errors */
+			/* fallthrough */
+
+#ifdef HPT_RESET_STATE_ENGINE
+	        case ide_dma_begin:
+#endif
+			pci_write_config_byte(hwif->pci_dev, regstate, 0x37);
+			udelay(10);
+			break;
+
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+int hpt37x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+	byte msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50;
+	byte bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01;
+
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_end:
+			pci_read_config_byte(dev, 0x6a, &bwsr_stat);
+			pci_read_config_byte(dev, mscreg, &msc_stat);
+			if ((bwsr_stat & bwsr_mask) == bwsr_mask)
+				pci_write_config_byte(dev, mscreg, msc_stat|0x30);
+			break;
+		case ide_dma_on:
+			if( !hpt37x_ide_dma_check_done ){
+				/* kernel parameter: ide0=noautotune or ide=nodma */
+				if( !hwif->autodma ){
+					/* kernel parameter: ide=nodma */
+
+					printk("HPT37X: Allow DMA\n");
+					hwif->autodma = 1;
+				}
+				(void) (HWIF(drive)->dmaproc(ide_dma_off_quietly, drive));
+				(void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
+			}
+			break;
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+/*
+ * Since SUN Cobalt is attempting to do this operation, I should disclose
+ * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
+ * HOTSWAP ATA Infrastructure.
+ */
+void hpt3xx_reset (ide_drive_t *drive)
+{
+#if 0
+	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
+	byte reset		= (HWIF(drive)->channel) ? 0x80 : 0x40;
+	byte reg59h		= 0;
+
+	pci_read_config_byte(HWIF(drive)->pci_dev, 0x59, &reg59h);
+	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h|reset);
+	pci_write_config_byte(HWIF(drive)->pci_dev, 0x59, reg59h);
+#endif
+}
+
+static int hpt3xx_tristate (ide_drive_t * drive, int state)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	byte reset		= (hwif->channel) ? 0x80 : 0x40;
+	byte state_reg		= (hwif->channel) ? 0x57 : 0x53;
+	byte reg59h		= 0;
+	byte regXXh		= 0;
+
+	if (!hwif)
+		return -EINVAL;
+
+//	hwif->bus_state = state;
+
+	pci_read_config_byte(dev, 0x59, &reg59h);
+	pci_read_config_byte(dev, state_reg, &regXXh);
+
+	if (state) {
+		(void) ide_do_reset(drive);
+		pci_write_config_byte(dev, state_reg, regXXh|0x80);
+		pci_write_config_byte(dev, 0x59, reg59h|reset);
+	} else {
+		pci_write_config_byte(dev, 0x59, reg59h & ~(reset));
+		pci_write_config_byte(dev, state_reg, regXXh & ~(0x80));
+		(void) ide_do_reset(drive);
+	}
+	return 0;
+}
+
+/* 
+ * set/get power state for a drive.
+ * turning the power off does the following things:
+ *   1) soft-reset the drive
+ *   2) tri-states the ide bus
+ *
+ * when we turn things back on, we need to re-initialize things.
+ */
+#define TRISTATE_BIT  0x8000
+static int hpt370_busproc(ide_drive_t * drive, int state)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	byte tristate, resetmask, bus_reg;
+	u16 tri_reg;
+
+	if (!hwif)
+		return -EINVAL;
+
+	hwif->bus_state = state;
+
+	if (hwif->channel) { 
+		/* secondary channel */
+		tristate = 0x56;
+		resetmask = 0x80; 
+	} else { 
+		/* primary channel */
+		tristate = 0x52;
+		resetmask = 0x40;
+	}
+
+	/* grab status */
+	pci_read_config_word(hwif->pci_dev, tristate, &tri_reg);
+	pci_read_config_byte(hwif->pci_dev, 0x59, &bus_reg);
+
+	/* set the state. we don't set it if we don't need to do so.
+	 * make sure that the drive knows that it has failed if it's off */
+	switch (state) {
+	case BUSSTATE_ON:
+		hwif->drives[0].failures = 0;
+		hwif->drives[1].failures = 0;
+		if ((bus_reg & resetmask) == 0)
+			return 0;
+		tri_reg &= ~TRISTATE_BIT;
+		bus_reg &= ~resetmask;
+		break;
+	case BUSSTATE_OFF:
+		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+		if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask))
+			return 0;
+		tri_reg &= ~TRISTATE_BIT;
+		bus_reg |= resetmask;
+		break;
+	case BUSSTATE_TRISTATE:
+		hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
+		hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
+		if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask))
+			return 0;
+		tri_reg |= TRISTATE_BIT;
+		bus_reg |= resetmask;
+		break;
+	}
+	pci_write_config_byte(hwif->pci_dev, 0x59, bus_reg);
+	pci_write_config_word(hwif->pci_dev, tristate, tri_reg);
+
+	return 0;
+}
+
+static int __init init_hpt37x(struct pci_dev *dev)
+{
+	int adjust, i;
+	u16 freq;
+	u32 pll;
+	byte reg5bh;
+
+#if 1
+	u8 reg5ah = 0;
+	pci_read_config_byte(dev, 0x5a, &reg5ah);
+	/* interrupt force enable */
+	pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
+#endif
+
+	/*
+	 * default to pci clock. make sure MA15/16 are set to output
+	 * to prevent drives having problems with 40-pin cables.
+	 */
+	pci_write_config_byte(dev, 0x5b, 0x23);
+
+	/*
+	 * set up the PLL. we need to adjust it so that it's stable. 
+	 * freq = Tpll * 192 / Tpci
+	 */
+	pci_read_config_word(dev, 0x78, &freq);
+	freq &= 0x1FF;
+	if (freq < 0x9c) {
+		pll = F_LOW_PCI_33;
+		if (hpt_minimum_revision(dev,8))
+			pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
+		else if (hpt_minimum_revision(dev,5))
+			pci_set_drvdata(dev, (void *) thirty_three_base_hpt372);
+		else if (hpt_minimum_revision(dev,4))
+			pci_set_drvdata(dev, (void *) thirty_three_base_hpt370a);
+		else
+			pci_set_drvdata(dev, (void *) thirty_three_base_hpt370);
+		printk("HPT37X: using 33MHz PCI clock\n");
+	} else if (freq < 0xb0) {
+		pll = F_LOW_PCI_40;
+	} else if (freq < 0xc8) {
+		pll = F_LOW_PCI_50;
+		if (hpt_minimum_revision(dev,8))
+			pci_set_drvdata(dev, (void *) NULL);
+		else if (hpt_minimum_revision(dev,5))
+			pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+		else if (hpt_minimum_revision(dev,4))
+			pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+		else
+			pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+		
+		printk("HPT37X: using 50MHz PCI clock\n");
+	} else {
+		pll = F_LOW_PCI_66;
+		if (hpt_minimum_revision(dev,8)){
+			printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n");
+			pci_set_drvdata(dev, (void *) NULL);
+		}else if (hpt_minimum_revision(dev,5))
+			pci_set_drvdata(dev, (void *) sixty_six_base_hpt372);
+		else if (hpt_minimum_revision(dev,4))
+			pci_set_drvdata(dev, (void *) sixty_six_base_hpt370a);
+		else
+			pci_set_drvdata(dev, (void *) sixty_six_base_hpt370);
+		printk("HPT37X: using 66MHz PCI clock\n");
+	}
+	
+	/*
+	 * only try the pll if we don't have a table for the clock
+	 * speed that we're running at. NOTE: the internal PLL will
+	 * result in slow reads when using a 33MHz PCI clock. we also
+	 * don't like to use the PLL because it will cause glitches
+	 * on PRST/SRST when the HPT state engine gets reset.
+	 */
+	if (pci_get_drvdata(dev)) 
+		goto init_hpt37X_done;
+	
+	/*
+	 * adjust PLL based upon PCI clock, enable it, and wait for
+	 * stabilization.
+	 */
+	adjust = 0;
+	freq = (pll < F_LOW_PCI_50) ? 2 : 4;
+	while (adjust++ < 6) {
+		pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |
+				       pll | 0x100);
+
+		/* wait for clock stabilization */
+		for (i = 0; i < 0x50000; i++) {
+			pci_read_config_byte(dev, 0x5b, &reg5bh);
+			if (reg5bh & 0x80) {
+				/* spin looking for the clock to destabilize */
+				for (i = 0; i < 0x1000; ++i) {
+					pci_read_config_byte(dev, 0x5b, 
+							     &reg5bh);
+					if ((reg5bh & 0x80) == 0)
+						goto pll_recal;
+				}
+				pci_read_config_dword(dev, 0x5c, &pll);
+				pci_write_config_dword(dev, 0x5c, 
+						       pll & ~0x100);
+				pci_write_config_byte(dev, 0x5b, 0x21);
+				if (hpt_minimum_revision(dev,8))
+					return -EOPNOTSUPP;
+				else if (hpt_minimum_revision(dev,5))
+					pci_set_drvdata(dev, (void *) fifty_base_hpt372);
+				else if (hpt_minimum_revision(dev,4))
+					pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+				else
+					pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
+				printk("HPT37X: using 50MHz internal PLL\n");
+				goto init_hpt37X_done;
+			}
+		}
+pll_recal:
+		if (adjust & 1)
+			pll -= (adjust >> 1);
+		else
+			pll += (adjust >> 1);
+	} 
+
+init_hpt37X_done:
+	/* reset state engine */
+	pci_write_config_byte(dev, 0x50, 0x37);
+	pci_write_config_byte(dev, 0x54, 0x37); 
+	udelay(100);
+	return 0;
+}
+
+static int __init init_hpt366 (struct pci_dev *dev)
+{
+	u32 reg1	= 0;
+	u8 drive_fast	= 0;
+
+	/*
+	 * Disable the "fast interrupt" prediction.
+	 */
+	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, &reg1);
+									
+	/* detect bus speed by looking at control reg timing: */
+	switch((reg1 >> 8) & 7) {
+		case 5:
+			pci_set_drvdata(dev, (void *) forty_base_hpt366);
+			break;
+		case 9:
+			pci_set_drvdata(dev, (void *) twenty_five_base_hpt366);
+			break;
+		case 7:
+		default:
+			pci_set_drvdata(dev, (void *) thirty_three_base_hpt366);
+			break;
+	}
+
+	if (pci_get_drvdata(dev))
+	{
+		printk(KERN_ERR "hpt366: unknown bus timing.\n");
+		pci_set_drvdata(dev, (void *) NULL);
+	}
+	return 0;
+}
+
+unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
+{
+	int ret = 0;
+	byte test = 0;
+
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+
+	pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test);
+	if (test != (L1_CACHE_BYTES / 4))
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
+
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test);
+	if (test != 0x78)
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+
+	pci_read_config_byte(dev, PCI_MIN_GNT, &test);
+	if (test != 0x08)
+		pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
+
+	pci_read_config_byte(dev, PCI_MAX_LAT, &test);
+	if (test != 0x08)
+		pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
+
+	if (hpt_minimum_revision(dev, 3)) {
+		ret = init_hpt37x(dev);
+	} else {
+		ret = init_hpt366(dev);
+	}
+
+	if (ret)
+		return ret;
+	hpt_devs[n_hpt_devs++] = dev;
+	
+#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!hpt366_proc) {
+		hpt366_proc = 1;
+		hpt366_display_info = &hpt366_get_info;
+	}
+#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
+
+	return dev->irq;
+}
+
+unsigned int __init ata66_hpt366 (ide_hwif_t *hwif)
+{
+	byte ata66	= 0;
+	byte regmask	= (hwif->channel) ? 0x01 : 0x02;
+
+	pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66);
+#ifdef DEBUG
+	printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
+		ata66, (ata66 & regmask) ? "33" : "66",
+		PCI_FUNC(hwif->pci_dev->devfn));
+#endif /* DEBUG */
+	return ((ata66 & regmask) ? 0 : 1);
+}
+
+void __init ide_init_hpt366 (ide_hwif_t *hwif)
+{
+	hwif->tuneproc	= &hpt3xx_tune_drive;
+	hwif->speedproc	= &hpt3xx_tune_chipset;
+	hwif->quirkproc	= &hpt3xx_quirkproc;
+	hwif->intrproc	= &hpt3xx_intrproc;
+	hwif->maskproc	= &hpt3xx_maskproc;
+
+#ifdef HPT_SERIALIZE_IO
+	/* serialize access to this device */
+	if (hwif->mate)
+		hwif->serialized = hwif->mate->serialized = 1;
+#endif
+
+	if (hpt_minimum_revision(hwif->pci_dev,3)) {
+		u8 reg5ah = 0;
+			pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10);
+		/*
+		 * set up ioctl for power status.
+		 * note: power affects both
+		 * drives on each channel
+		 */
+		hwif->resetproc	= &hpt3xx_reset;
+		hwif->busproc	= &hpt370_busproc;
+	} else if (hpt_minimum_revision(hwif->pci_dev,2)) {
+		hwif->resetproc	= &hpt3xx_reset;
+		hwif->busproc	= &hpt3xx_tristate;
+	} else {
+		hwif->resetproc = &hpt3xx_reset;
+		hwif->busproc   = &hpt3xx_tristate;
+	}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	if (hwif->dma_base) {
+		if (hpt_minimum_revision(hwif->pci_dev,5)) {
+			hwif->dmaproc = &hpt37x_dmaproc;
+		}else if (hpt_minimum_revision(hwif->pci_dev,3)) {	/* xxx */
+			byte reg5ah = 0;
+			pci_read_config_byte(hwif->pci_dev, 0x5a, &reg5ah);
+			if (reg5ah & 0x10)	/* interrupt force enable */
+				pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10);
+			hwif->dmaproc = &hpt370_dmaproc;
+		} else {
+			hwif->dmaproc = &hpt366_dmaproc;
+		}
+		if (!noautodma)
+			hwif->autodma = 1;
+	} else {
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+#else /* !CONFIG_BLK_DEV_IDEDMA */
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+	hwif->autodma = 0;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+}
+
+void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
+{
+	byte masterdma = 0, slavedma = 0;
+	byte dma_m_new, dma_m_old = inb(dmabase+0x2);
+	byte dma_s_new, dma_s_old = inb(dmabase+0xa);
+	byte primary	= hwif->channel ? 0x4b : 0x43;
+	byte secondary	= hwif->channel ? 0x4f : 0x47;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	dma_m_new = dma_m_old;
+	dma_s_new = dma_s_old;
+	pci_read_config_byte(hwif->pci_dev, primary, &masterdma);
+	pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);
+
+	if (masterdma & 0x30)	dma_m_new |= 0x60;
+	if (slavedma & 0x30)	dma_s_new |= 0x40;
+	if (dma_m_new != dma_m_old) outb(dma_m_new, dmabase+0x2);
+	if (dma_s_new != dma_s_old) outb(dma_s_new, dmabase+0xa);
+
+	local_irq_restore(flags);
+
+	ide_setup_dma(hwif, dmabase, 8);
+}
diff -Naur linux-2.6.0-test10/drivers/ide/ide-disk.c linux-2.6.0-test10-obs266/drivers/ide/ide-disk.c
--- linux-2.6.0-test10/drivers/ide/ide-disk.c	Mon Nov 24 10:31:49 2003
+++ linux-2.6.0-test10-obs266/drivers/ide/ide-disk.c	Wed Nov 26 18:24:08 2003
@@ -1692,6 +1692,13 @@
 	if (drive->using_dma)
 		HWIF(drive)->ide_dma_queued_on(drive);
 #endif
+
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	{
+		extern int obsled_out(int);
+		obsled_out(4);
+	}
+#endif
 }
 
 static int idedisk_cleanup (ide_drive_t *drive)
diff -Naur linux-2.6.0-test10/drivers/ide/ide-pci.c linux-2.6.0-test10-obs266/drivers/ide/ide-pci.c
--- linux-2.6.0-test10/drivers/ide/ide-pci.c	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/drivers/ide/ide-pci.c	Wed Nov 26 18:29:32 2003
@@ -0,0 +1,979 @@
+/*
+ *  linux/drivers/ide/ide-pci.c		Version 1.05	June 9, 2000
+ *
+ *  Copyright (c) 1998-2000  Andre Hedrick <andre@linux-ide.org>
+ *
+ *  Copyright (c) 1995-1998  Mark Lord
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+/*
+ *  This module provides support for automatic detection and
+ *  configuration of all PCI IDE interfaces present in a system.  
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define DEVID_PIIXa	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_0})
+#define DEVID_PIIXb	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_1})
+#define DEVID_MPIIX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371MX})
+#define DEVID_PIIX3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
+#define DEVID_PIIX4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
+#define DEVID_PIIX4E	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_PIIX4E2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82443MX_1})
+#define DEVID_PIIX4U	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
+#define DEVID_PIIX4U2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82372FB_1})
+#define DEVID_PIIX4NX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82451NX})
+#define DEVID_PIIX4U3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
+#define DEVID_PIIX4U4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
+#define DEVID_PIIX4U5	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801CA_10})
+#define DEVID_VIA_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C561})
+#define DEVID_MR_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C576_1})
+#define DEVID_VP_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_1})
+#define DEVID_PDC20246	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
+#define DEVID_PDC20262	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
+#define DEVID_PDC20265	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20265})
+#define DEVID_PDC20267	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20267})
+#define DEVID_PDC20268  ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268})
+#define DEVID_PDC20268R ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R})
+#define DEVID_PDC20269	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269})
+#define DEVID_PDC20275	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275})
+#define DEVID_RZ1000	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1000})
+#define DEVID_RZ1001	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1001})
+#define DEVID_SAMURAI	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_SAMURAI_IDE})
+#define DEVID_CMD640	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_640})
+#define DEVID_CMD643	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_643})
+#define DEVID_CMD646	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_646})
+#define DEVID_CMD648	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_648})
+#define DEVID_CMD649	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_649})
+#define DEVID_CMD680	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_680})
+#define DEVID_SIS5513	((ide_pci_devid_t){PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5513})
+#define DEVID_OPTI621	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C621})
+#define DEVID_OPTI621V	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C558})
+#define DEVID_OPTI621X	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C825})
+#define DEVID_TRM290	((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM,  PCI_DEVICE_ID_TEKRAM_DC290})
+#define DEVID_NS87410	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87410})
+#define DEVID_NS87415	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87415})
+#define DEVID_HT6565	((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK,  PCI_DEVICE_ID_HOLTEK_6565})
+#define DEVID_AEC6210	((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP850UF})
+#define DEVID_AEC6260	((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP860})
+#define DEVID_AEC6260R	((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP860R})
+#define DEVID_AEC6280	((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP865})
+#define DEVID_AEC6280R	((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP,   PCI_DEVICE_ID_ARTOP_ATP865R})
+#define DEVID_W82C105	((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
+#define DEVID_UM8673F	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8673F})
+#define DEVID_UM8886A	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886A})
+#define DEVID_UM8886BF	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886BF})
+#define DEVID_HPT34X	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT343})
+#define DEVID_HPT366	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT366})
+#define DEVID_HPT371	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     0x0007})
+#define DEVID_ALI15X3	((ide_pci_devid_t){PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M5229})
+#define DEVID_CY82C693	((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
+#define DEVID_HINT	((ide_pci_devid_t){0x3388,                0x8013})
+#define DEVID_CS5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
+#define DEVID_AMD7401	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7401})
+#define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
+#define DEVID_AMD7411	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7411})
+#define DEVID_PDCADMA	((ide_pci_devid_t){PCI_VENDOR_ID_PDC,     PCI_DEVICE_ID_PDC_1841})
+#define DEVID_SLC90E66	((ide_pci_devid_t){PCI_VENDOR_ID_EFAR,    PCI_DEVICE_ID_EFAR_SLC90E66_1})
+#define DEVID_OSB4	((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE})
+#define DEVID_CSB5	((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE})
+#define DEVID_ITE8172G	((ide_pci_devid_t){PCI_VENDOR_ID_ITE,     PCI_DEVICE_ID_ITE_IT8172G})
+#define DEVID_XILLEON	((ide_pci_devid_t){PCI_VENDOR_ID_ATI,     PCI_DEVICE_ID_ATI_XILLEON_IDE})
+
+#define	IDE_IGNORE	((void *)-1)
+
+#ifdef CONFIG_BLK_DEV_AEC62XX
+extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *);
+extern unsigned int ata66_aec62xx(ide_hwif_t *);
+extern void ide_init_aec62xx(ide_hwif_t *);
+extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
+#define PCI_AEC62XX	&pci_init_aec62xx
+#define ATA66_AEC62XX	&ata66_aec62xx
+#define INIT_AEC62XX	&ide_init_aec62xx
+#define DMA_AEC62XX	&ide_dmacapable_aec62xx
+#else
+#define PCI_AEC62XX	NULL
+#define ATA66_AEC62XX	NULL
+#define INIT_AEC62XX	NULL
+#define DMA_AEC62XX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_ALI15X3
+extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *);
+extern unsigned int ata66_ali15x3(ide_hwif_t *);
+extern void ide_init_ali15x3(ide_hwif_t *);
+extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long);
+#define PCI_ALI15X3	&pci_init_ali15x3
+#define ATA66_ALI15X3	&ata66_ali15x3
+#define INIT_ALI15X3	&ide_init_ali15x3
+#define DMA_ALI15X3	&ide_dmacapable_ali15x3
+#else
+#define PCI_ALI15X3	NULL
+#define ATA66_ALI15X3	NULL
+#define INIT_ALI15X3	NULL
+#define DMA_ALI15X3	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_AMD74XX
+extern unsigned int pci_init_amd74xx(struct pci_dev *, const char *);
+extern unsigned int ata66_amd74xx(ide_hwif_t *);
+extern void ide_init_amd74xx(ide_hwif_t *);
+extern void ide_dmacapable_amd74xx(ide_hwif_t *, unsigned long);
+#define PCI_AMD74XX	&pci_init_amd74xx
+#define ATA66_AMD74XX	&ata66_amd74xx
+#define INIT_AMD74XX	&ide_init_amd74xx
+#define DMA_AMD74XX	&ide_dmacapable_amd74xx
+#else
+#define PCI_AMD74XX	NULL
+#define ATA66_AMD74XX	NULL
+#define INIT_AMD74XX	NULL
+#define DMA_AMD74XX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_CMD64X
+extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *);
+extern unsigned int ata66_cmd64x(ide_hwif_t *);
+extern void ide_init_cmd64x(ide_hwif_t *);
+extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long);
+#define PCI_CMD64X	&pci_init_cmd64x
+#define ATA66_CMD64X	&ata66_cmd64x
+#define INIT_CMD64X	&ide_init_cmd64x
+#else
+#define PCI_CMD64X	NULL
+#define ATA66_CMD64X	NULL
+#ifdef __sparc_v9__
+#define INIT_CMD64X	IDE_IGNORE
+#else
+#define INIT_CMD64X	NULL
+#endif
+#endif
+
+#ifdef CONFIG_BLK_DEV_CY82C693
+extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *);
+extern void ide_init_cy82c693(ide_hwif_t *);
+#define PCI_CY82C693	&pci_init_cy82c693
+#define INIT_CY82C693	&ide_init_cy82c693
+#else
+#define PCI_CY82C693	NULL
+#define INIT_CY82C693	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_CS5530
+extern unsigned int pci_init_cs5530(struct pci_dev *, const char *);
+extern void ide_init_cs5530(ide_hwif_t *);
+#define PCI_CS5530	&pci_init_cs5530
+#define INIT_CS5530	&ide_init_cs5530
+#else
+#define PCI_CS5530	NULL
+#define INIT_CS5530	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_HPT34X
+extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *);
+extern void ide_init_hpt34x(ide_hwif_t *);
+#define PCI_HPT34X	&pci_init_hpt34x
+#define INIT_HPT34X	&ide_init_hpt34x
+#else
+#define PCI_HPT34X	NULL
+#define INIT_HPT34X	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_HPT366
+extern byte hpt363_shared_irq;
+extern byte hpt363_shared_pin;
+extern unsigned int pci_init_hpt366(struct pci_dev *, const char *);
+extern unsigned int ata66_hpt366(ide_hwif_t *);
+extern void ide_init_hpt366(ide_hwif_t *);
+extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long);
+#define PCI_HPT366	&pci_init_hpt366
+#define ATA66_HPT366	&ata66_hpt366
+#define INIT_HPT366	&ide_init_hpt366
+#define DMA_HPT366	&ide_dmacapable_hpt366
+#else
+static byte hpt363_shared_irq;
+static byte hpt363_shared_pin;
+#define PCI_HPT366	NULL
+#define ATA66_HPT366	NULL
+#define INIT_HPT366	NULL
+#define DMA_HPT366	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_NS87415
+extern void ide_init_ns87415(ide_hwif_t *);
+#define INIT_NS87415	&ide_init_ns87415
+#else
+#define INIT_NS87415	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_OPTI621
+extern void ide_init_opti621(ide_hwif_t *);
+#define INIT_OPTI621	&ide_init_opti621
+#else
+#define INIT_OPTI621	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PDC_ADMA
+extern unsigned int pci_init_pdcadma(struct pci_dev *, const char *);
+extern unsigned int ata66_pdcadma(ide_hwif_t *);
+extern void ide_init_pdcadma(ide_hwif_t *);
+extern void ide_dmacapable_pdcadma(ide_hwif_t *, unsigned long);
+#define PCI_PDCADMA	&pci_init_pdcadma
+#define ATA66_PDCADMA	&ata66_pdcadma
+#define INIT_PDCADMA	&ide_init_pdcadma
+#define DMA_PDCADMA	&ide_dmacapable_pdcadma
+#else
+#define PCI_PDCADMA	IDE_IGNORE
+#define ATA66_PDCADMA	IDE_IGNORE
+#define INIT_PDCADMA	IDE_IGNORE
+#define DMA_PDCADMA	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_PDC202XX
+extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
+extern unsigned int ata66_pdc202xx(ide_hwif_t *);
+extern void ide_init_pdc202xx(ide_hwif_t *);
+#define PCI_PDC202XX	&pci_init_pdc202xx
+#define ATA66_PDC202XX	&ata66_pdc202xx
+#define INIT_PDC202XX	&ide_init_pdc202xx
+#else
+#define PCI_PDC202XX	NULL
+#define ATA66_PDC202XX	NULL
+#define INIT_PDC202XX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PIIX
+extern unsigned int pci_init_piix(struct pci_dev *, const char *);
+extern unsigned int ata66_piix(ide_hwif_t *);
+extern void ide_init_piix(ide_hwif_t *);
+#define PCI_PIIX	&pci_init_piix
+#define ATA66_PIIX	&ata66_piix
+#define INIT_PIIX	&ide_init_piix
+#else
+#define PCI_PIIX	NULL
+#define ATA66_PIIX	NULL
+#define INIT_PIIX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_IT8172
+extern unsigned int pci_init_it8172(struct pci_dev *, const char *);
+extern unsigned int ata66_it8172(ide_hwif_t *);
+extern void ide_init_it8172(ide_hwif_t *);
+#define PCI_IT8172	&pci_init_it8172
+#define INIT_IT8172	&ide_init_it8172
+#else
+#define PCI_IT8172	NULL
+#define ATA66_IT8172	NULL
+#define INIT_IT8172	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_XILLEON
+extern unsigned int pci_init_xilleon_ide(struct pci_dev *, const char *);
+extern unsigned int ata66_xilleon(ide_hwif_t *);
+extern void ide_init_xilleon(ide_hwif_t *);
+extern void ide_dmacapable_xilleon(ide_hwif_t *, unsigned long);
+#define PCI_XILLEON	&pci_init_xilleon_ide
+#define ATA66_XILLEON  &ata66_xilleon
+#define INIT_XILLEON	&ide_init_xilleon
+#define DMA_XILLEON	&ide_dmacapable_xilleon
+#else
+#define PCI_XILLEON	NULL
+#define ATA66_XILLEON	NULL
+#define INIT_XILLEON	NULL
+#define DMA_XILLEON	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_RZ1000
+extern void ide_init_rz1000(ide_hwif_t *);
+#define INIT_RZ1000	&ide_init_rz1000
+#else
+#define INIT_RZ1000	IDE_IGNORE
+#endif
+
+#define INIT_SAMURAI	NULL
+
+#ifdef CONFIG_BLK_DEV_SVWKS
+extern unsigned int pci_init_svwks(struct pci_dev *, const char *);
+extern unsigned int ata66_svwks(ide_hwif_t *);
+extern void ide_init_svwks(ide_hwif_t *);
+#define PCI_SVWKS	&pci_init_svwks
+#define ATA66_SVWKS	&ata66_svwks
+#define INIT_SVWKS	&ide_init_svwks
+#else
+#define PCI_SVWKS	NULL
+#define ATA66_SVWKS	NULL
+#define INIT_SVWKS	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_SIS5513
+extern unsigned int pci_init_sis5513(struct pci_dev *, const char *);
+extern unsigned int ata66_sis5513(ide_hwif_t *);
+extern void ide_init_sis5513(ide_hwif_t *);
+#define PCI_SIS5513	&pci_init_sis5513
+#define ATA66_SIS5513	&ata66_sis5513
+#define INIT_SIS5513	&ide_init_sis5513
+#else
+#define PCI_SIS5513	NULL
+#define ATA66_SIS5513	NULL
+#define INIT_SIS5513	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_SLC90E66
+extern unsigned int pci_init_slc90e66(struct pci_dev *, const char *);
+extern unsigned int ata66_slc90e66(ide_hwif_t *);
+extern void ide_init_slc90e66(ide_hwif_t *);
+#define PCI_SLC90E66	&pci_init_slc90e66
+#define ATA66_SLC90E66	&ata66_slc90e66
+#define INIT_SLC90E66	&ide_init_slc90e66
+#else
+#define PCI_SLC90E66	NULL
+#define ATA66_SLC90E66	NULL
+#define INIT_SLC90E66	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_SL82C105
+extern unsigned int pci_init_sl82c105(struct pci_dev *, const char *);
+extern void dma_init_sl82c105(ide_hwif_t *, unsigned long);
+extern void ide_init_sl82c105(ide_hwif_t *);
+#define PCI_W82C105	&pci_init_sl82c105
+#define DMA_W82C105	&dma_init_sl82c105
+#define INIT_W82C105	&ide_init_sl82c105
+#else
+#define PCI_W82C105	NULL
+#define DMA_W82C105	NULL
+#define INIT_W82C105	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_TRM290
+extern void ide_init_trm290(ide_hwif_t *);
+#define INIT_TRM290	&ide_init_trm290
+#else
+#define INIT_TRM290	IDE_IGNORE
+#endif
+
+#ifdef CONFIG_BLK_DEV_VIA82CXXX
+extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *);
+extern unsigned int ata66_via82cxxx(ide_hwif_t *);
+extern void ide_init_via82cxxx(ide_hwif_t *);
+extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long);
+#define PCI_VIA82CXXX	&pci_init_via82cxxx
+#define ATA66_VIA82CXXX	&ata66_via82cxxx
+#define INIT_VIA82CXXX	&ide_init_via82cxxx
+#define DMA_VIA82CXXX	&ide_dmacapable_via82cxxx
+#else
+#define PCI_VIA82CXXX	NULL
+#define ATA66_VIA82CXXX	NULL
+#define INIT_VIA82CXXX	NULL
+#define DMA_VIA82CXXX	NULL
+#endif
+
+typedef struct ide_pci_enablebit_s {
+	byte	reg;	/* byte pci reg holding the enable-bit */
+	byte	mask;	/* mask to isolate the enable-bit */
+	byte	val;	/* value of masked reg when "enabled" */
+} ide_pci_enablebit_t;
+
+typedef struct ide_pci_device_s {
+	ide_pci_devid_t		devid;
+	char			*name;
+	unsigned int		(*init_chipset)(struct pci_dev *dev, const char *name);
+	unsigned int		(*ata66_check)(ide_hwif_t *hwif);
+	void 			(*init_hwif)(ide_hwif_t *hwif);
+	void			(*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
+	ide_pci_enablebit_t	enablebits[2];
+	byte			bootable;
+	unsigned int		extra;
+} ide_pci_device_t;
+
+static ide_pci_device_t ide_pci_chipsets[] __initdata = {
+	{DEVID_PIIXa,	"PIIX",		NULL,		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIXb,	"PIIX",		NULL,		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_MPIIX,	"MPIIX",	NULL,		NULL,		INIT_PIIX,	NULL,		{{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX3,	"PIIX3",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX4,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX4E,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4E2,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U2,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4NX,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U3,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U4, "PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4U5, "PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_VIA_IDE,	"VIA_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_MR_IDE,	"VP_IDE",	PCI_VIA82CXXX,	ATA66_VIA82CXXX,INIT_VIA82CXXX,	DMA_VIA82CXXX,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+	{DEVID_VP_IDE,	"VP_IDE",	PCI_VIA82CXXX,	ATA66_VIA82CXXX,INIT_VIA82CXXX,	DMA_VIA82CXXX,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+#ifdef CONFIG_PDC202XX_FORCE
+        {DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	NULL,		INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+        {DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+        {DEVID_PDC20265,"PDC20265",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+        {DEVID_PDC20267,"PDC20267",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	48 },
+#else /* !CONFIG_PDC202XX_FORCE */
+	{DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	NULL,		INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
+	{DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+	{DEVID_PDC20265,"PDC20265",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+	{DEVID_PDC20267,"PDC20267",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+#endif
+	{DEVID_PDC20268,"PDC20268",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+	/* Promise used a different PCI ident for the raid card apparently to try and
+	   prevent Linux detecting it and using our own raid code. We want to detect
+	   it for the ataraid drivers, so we have to list both here.. */
+	{DEVID_PDC20268R,"PDC20268",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+	{DEVID_PDC20269,"PDC20269",	PCI_PDC202XX,	ATA66_PDC202XX,	 INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+	{DEVID_PDC20275,"PDC20275",	PCI_PDC202XX,	ATA66_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	16 },
+	{DEVID_RZ1000,	"RZ1000",	NULL,		NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_RZ1001,	"RZ1001",	NULL,		NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_SAMURAI,	"SAMURAI",	NULL,		NULL,		INIT_SAMURAI,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD640,	"CMD640",	NULL,		NULL,		IDE_IGNORE,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87410,	"NS87410",	NULL,		NULL,		NULL,		NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
+	{DEVID_SIS5513,	"SIS5513",	PCI_SIS5513,	ATA66_SIS5513,	INIT_SIS5513,	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
+	{DEVID_CMD643,	"CMD643",	PCI_CMD64X,	NULL,		INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD646,	"CMD646",	PCI_CMD64X,	NULL,		INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_CMD648,	"CMD648",	PCI_CMD64X,	ATA66_CMD64X,	INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD649,	"CMD649",	PCI_CMD64X,	ATA66_CMD64X,	INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD680,	"CMD680",	PCI_CMD64X,	ATA66_CMD64X,	INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_HT6565,	"HT6565",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621,	"OPTI621",	NULL,		NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621X,"OPTI621X",	NULL,		NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_TRM290,	"TRM290",	NULL,		NULL,		INIT_TRM290,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87415,	"NS87415",	NULL,		NULL,		INIT_NS87415,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_AEC6210,	"AEC6210",	PCI_AEC62XX,	NULL,		INIT_AEC62XX,	DMA_AEC62XX,	{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	OFF_BOARD,	0 },
+	{DEVID_AEC6260,	"AEC6260",	PCI_AEC62XX,	ATA66_AEC62XX,	INIT_AEC62XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	0 },
+	{DEVID_AEC6260R,"AEC6260R",	PCI_AEC62XX,	ATA66_AEC62XX,	INIT_AEC62XX,	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},	OFF_BOARD,	0 },
+	{DEVID_AEC6280,	"AEC6280",	PCI_AEC62XX,	ATA66_AEC62XX,	INIT_AEC62XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	0 },
+	{DEVID_AEC6280R,"AEC6280R",	PCI_AEC62XX,	ATA66_AEC62XX,	INIT_AEC62XX,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	0 },
+	{DEVID_W82C105,	"W82C105",	PCI_W82C105,	NULL,		INIT_W82C105,	DMA_W82C105,	{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
+	{DEVID_UM8673F,	"UM8673F",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_UM8886A,	"UM8886A",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_UM8886BF,"UM8886BF",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_HPT34X,	"HPT34X",	PCI_HPT34X,	NULL,		INIT_HPT34X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
+	{DEVID_HPT366,	"HPT366",	PCI_HPT366,	ATA66_HPT366,	INIT_HPT366,	DMA_HPT366,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	240 },
+	{DEVID_HPT371,	"HPT371",	PCI_HPT366,	ATA66_HPT366,	INIT_HPT366,	DMA_HPT366,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD, 0 },
+	{DEVID_ALI15X3,	"ALI15X3",	PCI_ALI15X3,	ATA66_ALI15X3,	INIT_ALI15X3,	DMA_ALI15X3,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CY82C693,"CY82C693",	PCI_CY82C693,	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CS5530,	"CS5530",	PCI_CS5530,	NULL,		INIT_CS5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_AMD7401,	"AMD7401",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_AMD7409,	"AMD7409",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_AMD7411,	"AMD7411",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_PDCADMA,	"PDCADMA",	PCI_PDCADMA,	ATA66_PDCADMA,	INIT_PDCADMA,	DMA_PDCADMA,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	0 },
+	{DEVID_SLC90E66,"SLC90E66",	PCI_SLC90E66,	ATA66_SLC90E66,	INIT_SLC90E66,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+        {DEVID_OSB4,    "ServerWorks OSB4",		PCI_SVWKS,	ATA66_SVWKS,	INIT_SVWKS,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CSB5,	"ServerWorks CSB5",		PCI_SVWKS,	ATA66_SVWKS,	INIT_SVWKS,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_ITE8172G,"IT8172G",	PCI_IT8172,	NULL,	INIT_IT8172,	NULL,		{{0x00,0x00,0x00}, {0x40,0x00,0x01}},	ON_BOARD,	0 },
+	{DEVID_XILLEON, "XILLEON",	PCI_XILLEON,	ATA66_XILLEON,  INIT_XILLEON,   DMA_XILLEON,  	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
+
+/*
+ * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
+ * settings of split-mirror pci-config space, place chipset into init-mode,
+ * and/or preserve an interrupt if the card is not native ide support.
+ */
+static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name)
+{
+	switch(dev->device) {
+		case PCI_DEVICE_ID_TTI_HPT366:
+		case PCI_DEVICE_ID_PROMISE_20246:
+		case PCI_DEVICE_ID_PROMISE_20262:
+		case PCI_DEVICE_ID_PROMISE_20265:
+		case PCI_DEVICE_ID_PROMISE_20267:
+		case PCI_DEVICE_ID_PROMISE_20268:
+		case PCI_DEVICE_ID_PROMISE_20268R:
+		case PCI_DEVICE_ID_PROMISE_20269:
+		case PCI_DEVICE_ID_PROMISE_20275:
+		case PCI_DEVICE_ID_ARTOP_ATP850UF:
+		case PCI_DEVICE_ID_ARTOP_ATP860:
+		case PCI_DEVICE_ID_ARTOP_ATP860R:
+		case PCI_DEVICE_ID_ARTOP_ATP865:
+		case PCI_DEVICE_ID_ARTOP_ATP865R:
+			return dev->irq;
+		default:
+			break;
+	}
+	return 0;
+}
+
+/*
+ * Match a PCI IDE port against an entry in ide_hwifs[],
+ * based on io_base port if possible.
+ */
+static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)
+{
+	int h;
+	ide_hwif_t *hwif;
+
+	/*
+	 * Look for a hwif with matching io_base specified using
+	 * parameters to ide_setup().
+	 */
+	for (h = 0; h < MAX_HWIFS; ++h) {
+		hwif = &ide_hwifs[h];
+		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+			if (hwif->chipset == ide_generic)
+				return hwif; /* a perfect match */
+		}
+	}
+	/*
+	 * Look for a hwif with matching io_base default value.
+	 * If chipset is "ide_unknown", then claim that hwif slot.
+	 * Otherwise, some other chipset has already claimed it..  :(
+	 */
+	for (h = 0; h < MAX_HWIFS; ++h) {
+		hwif = &ide_hwifs[h];
+		if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) {
+			if (hwif->chipset == ide_unknown)
+				return hwif; /* match */
+			printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name);
+			return NULL;	/* already claimed */
+		}
+	}
+	/*
+	 * Okay, there is no hwif matching our io_base,
+	 * so we'll just claim an unassigned slot.
+	 * Give preference to claiming other slots before claiming ide0/ide1,
+	 * just in case there's another interface yet-to-be-scanned
+	 * which uses ports 1f0/170 (the ide0/ide1 defaults).
+	 *
+	 * Unless there is a bootable card that does not use the standard
+	 * ports 1f0/170 (the ide0/ide1 defaults). The (bootable) flag.
+	 */
+	if (bootable) {
+		for (h = 0; h < MAX_HWIFS; ++h) {
+			hwif = &ide_hwifs[h];
+			if (hwif->chipset == ide_unknown)
+				return hwif;	/* pick an unused entry */
+		}
+	} else {
+		for (h = 2; h < MAX_HWIFS; ++h) {
+			hwif = ide_hwifs + h;
+			if (hwif->chipset == ide_unknown)
+				return hwif;	/* pick an unused entry */
+		}
+	}
+	for (h = 0; h < 2; ++h) {
+		hwif = ide_hwifs + h;
+		if (hwif->chipset == ide_unknown)
+			return hwif;	/* pick an unused entry */
+	}
+	printk("%s: too many IDE interfaces, no room in table\n", name);
+	return NULL;
+}
+
+static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
+{
+	byte reg, progif = 0;
+
+	/*
+	 * Place both IDE interfaces into PCI "native" mode:
+	 */
+	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
+		if ((progif & 0xa) != 0xa) {
+			printk("%s: device not capable of full native PCI mode\n", name);
+			return 1;
+		}
+		printk("%s: placing both ports into native PCI mode\n", name);
+		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
+		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) {
+			printk("%s: rewrite of PROGIF failed, wanted 0x%04x, got 0x%04x\n", name, progif|5, progif);
+			return 1;
+		}
+	}
+	/*
+	 * Setup base registers for IDE command/control spaces for each interface:
+	 */
+	for (reg = 0; reg < 4; reg++) {
+		struct resource *res = dev->resource + reg;
+		if ((res->flags & IORESOURCE_IO) == 0)
+			continue;
+		if (!res->start) {
+			printk("%s: Missing I/O address #%d\n", name, reg);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * ide_setup_pci_device() looks at the primary/secondary interfaces
+ * on a PCI IDE device and, if they are enabled, prepares the IDE driver
+ * for use with them.  This generic code works for most PCI chipsets.
+ *
+ * One thing that is not standardized is the location of the
+ * primary/secondary interface "enable/disable" bits.  For chipsets that
+ * we "know" about, this information is in the ide_pci_device_t struct;
+ * for all other chipsets, we just assume both interfaces are enabled.
+ */
+static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)
+{
+	unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0;
+	unsigned short pcicmd = 0, tried_config = 0;
+	byte tmp = 0;
+	ide_hwif_t *hwif, *mate = NULL;
+	unsigned int class_rev;
+	static int secondpdc = 0;
+
+#ifdef CONFIG_IDEDMA_AUTO
+	if (!noautodma)
+		autodma = 1;
+#endif
+
+	if (pci_enable_device(dev)) {
+		printk("%s: error while enabling PCI device\n", d->name);
+		return;
+	}
+
+check_if_enabled:
+	if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) {
+		printk("%s: error accessing PCI regs\n", d->name);
+		return;
+	}
+	if (!(pcicmd & PCI_COMMAND_IO)) {	/* is device disabled? */
+		/*
+		 * PnP BIOS was *supposed* to have set this device up for us,
+		 * but we can do it ourselves, so long as the BIOS has assigned an IRQ
+		 *  (or possibly the device is using a "legacy header" for IRQs).
+		 * Maybe the user deliberately *disabled* the device,
+		 * but we'll eventually ignore it again if no drives respond.
+		 */
+		if (tried_config++
+		 || ide_setup_pci_baseregs(dev, d->name)
+		 || pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_IO)) {
+			printk("%s: device disabled (BIOS)\n", d->name);
+			return;
+		}
+		autodma = 0;	/* default DMA off if we had to configure it here */
+		goto check_if_enabled;
+	}
+	if (tried_config)
+		printk("%s: device enabled (Linux)\n", d->name);
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) {
+		/* see comments in hpt34x.c on why..... */
+		char *chipset_names[] = {"HPT343", "HPT345"};
+		strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]);
+		d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD;
+	}
+
+	printk("%s: chipset revision %d\n", d->name, class_rev);
+
+	/*
+	 * Can we trust the reported IRQ?
+	 */
+	pciirq = dev->irq;
+	
+	if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID)
+	{
+		/* By rights we want to ignore these, but the Promise Fastrak
+		   people have some strange ideas about proprietary so we have
+		   to act otherwise on those. The supertrak however we need
+		   to skip */
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265))
+		{
+			printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n");
+			if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL &&
+				dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960)
+			{
+				printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n");
+				return;
+			}
+		}
+		/* Its attached to something else, just a random bridge. 
+		   Suspect a fastrak and fall through */
+	}
+	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
+		printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
+		/*
+		 * This allows offboard ide-pci cards the enable a BIOS,
+		 * verify interrupt settings of split-mirror pci-config
+		 * space, place chipset into init-mode, and/or preserve
+		 * an interrupt if the card is not native ide support.
+		 */
+		pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name);
+	} else if (tried_config) {
+		printk("%s: will probe irqs later\n", d->name);
+		pciirq = 0;
+	} else if (!pciirq) {
+		printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
+		pciirq = 0;
+	} else {
+		if (d->init_chipset)
+			(void) d->init_chipset(dev, d->name);
+#ifdef __sparc__
+		printk("%s: 100%% native mode on irq %s\n",
+		       d->name, __irq_itoa(pciirq));
+#else
+		printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
+#endif
+	}
+
+	/*
+	 * Set up the IDE ports
+	 */
+	for (port = 0; port <= 1; ++port) {
+		unsigned long base = 0, ctl = 0;
+		ide_pci_enablebit_t *e = &(d->enablebits[port]);
+	
+		/* 
+		 * If this is a Promise FakeRaid controller, the 2nd controller will be marked as 
+		 * disabled while it is actually there and enabled by the bios for raid purposes. 
+		 * Skip the normal "is it enabled" test for those.
+		 */
+		if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1)  ) 
+			goto controller_ok;
+		if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1)  ) 
+			goto controller_ok;
+			
+		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
+			continue;	/* port not enabled */
+controller_ok:			
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03))
+			return;
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_XILLEON) && (port))   /* no second port */
+			return;
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT371) && (port == 0))
+			continue;
+		if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
+			ctl  = dev->resource[(2*port)+1].start;
+			base = dev->resource[2*port].start;
+			if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) ||
+			    !(base & PCI_BASE_ADDRESS_IO_MASK)) {
+				printk("%s: IO baseregs (BIOS) are reported as MEM, report to <andre@linux-ide.org>.\n", d->name);
+#if 0
+				/* FIXME! This really should check that it really gets the IO/MEM part right! */
+				continue;
+#endif
+			}
+		}
+		if ((ctl && !base) || (base && !ctl)) {
+			printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port);
+			continue;
+		}
+		if (!ctl)
+			ctl = port ? 0x374 : 0x3f4;	/* use default value */
+		if (!base)
+			base = port ? 0x170 : 0x1f0;	/* use default value */
+		if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
+			continue;	/* no room in ide_hwifs[] */
+		if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
+			ide_init_hwif_ports(&hwif->hw, base, (ctl | 2), NULL);
+			memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+			hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+		}
+		hwif->chipset = ide_pci;
+		hwif->pci_dev = dev;
+		hwif->pci_devid = d->devid;
+		hwif->channel = port;
+		if (!hwif->irq)
+			hwif->irq = pciirq;
+		if (mate) {
+			hwif->mate = mate;
+			mate->mate = hwif;
+			if (IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210)) {
+				hwif->serialized = 1;
+				mate->serialized = 1;
+			}
+		}
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8673F)) {
+			hwif->irq = hwif->channel ? 15 : 14;
+			goto bypass_umc_dma;
+		}
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_MPIIX))
+			goto bypass_piix_dma;
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD680))
+			goto bypass_legacy_dma;
+		if (hwif->udma_four) {
+			printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name);
+		} else {
+			hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0;
+		}
+#ifdef CONFIG_BLK_DEV_IDEDMA
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PIIX4NX) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)  ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_VIA_IDE) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_MR_IDE)  ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_VP_IDE))
+			autodma = 0;
+		if (autodma)
+			hwif->autodma = 1;
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20267) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6280) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6280R) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT371) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD648) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD649) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_OSB4) ||
+		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
+			unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
+			if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
+				/*
+ 	 			 * Set up BM-DMA capability (PnP BIOS should have done this)
+ 	 			 */
+		    		if (!IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530))
+					hwif->autodma = 0;	/* default DMA off if we had to configure it here */
+				(void) pci_write_config_word(dev, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER);
+				if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd) || !(pcicmd & PCI_COMMAND_MASTER)) {
+					printk("%s: %s error updating PCICMD\n", hwif->name, d->name);
+					dma_base = 0;
+				}
+			}
+			if (dma_base) {
+				if (d->dma_init) {
+					d->dma_init(hwif, dma_base);
+				} else {
+					ide_setup_dma(hwif, dma_base, 8);
+				}
+			} else {
+				printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
+			}
+		}
+#endif	/* CONFIG_BLK_DEV_IDEDMA */
+bypass_legacy_dma:
+bypass_piix_dma:
+bypass_umc_dma:
+		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
+			d->init_hwif(hwif);
+		mate = hwif;
+		at_least_one_hwif_enabled = 1;
+	}
+	if (!at_least_one_hwif_enabled)
+		printk("%s: neither IDE port enabled (BIOS)\n", d->name);
+}
+
+static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
+{
+	struct pci_dev *dev2 = NULL, *findev;
+	ide_pci_device_t *d2;
+	unsigned char pin1 = 0, pin2 = 0;
+	unsigned int class_rev;
+	char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A"};
+
+	if (PCI_FUNC(dev->devfn) & 1)
+		return;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	strcpy(d->name, chipset_names[class_rev]);
+
+	switch(class_rev) {
+		case 4:
+		case 3:	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+			ide_setup_pci_device(dev, d);
+			return;
+		default:	break;
+	}
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
+	pci_for_each_dev(findev) {
+		if ((findev->vendor == dev->vendor) &&
+		    (findev->device == dev->device) &&
+		    ((findev->devfn - dev->devfn) == 1) &&
+		    (PCI_FUNC(findev->devfn) & 1)) {
+			dev2 = findev;
+			pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
+			hpt363_shared_pin = (pin1 != pin2) ? 1 : 0;
+			hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0;
+			if (hpt363_shared_pin && hpt363_shared_irq) {
+				d->bootable = ON_BOARD;
+				printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2);
+#if 0
+				/* I forgot why I did this once, but it fixed something. */
+				pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq);
+				printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2);
+				pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0);
+#endif
+			}
+			break;
+		}
+	}
+	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+	ide_setup_pci_device(dev, d);
+	if (!dev2)
+		return;
+	d2 = d;
+	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
+	ide_setup_pci_device(dev2, d2);
+}
+
+/*
+ * ide_scan_pcibus() gets invoked at boot time from ide.c.
+ * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
+ */
+void __init ide_scan_pcidev (struct pci_dev *dev)
+{
+	ide_pci_devid_t		devid;
+	ide_pci_device_t	*d;
+
+	devid.vid = dev->vendor;
+	devid.did = dev->device;
+	for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
+	if (d->init_hwif == IDE_IGNORE)
+		printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
+		return;
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+		return;	/* CY82C693 is more than only a IDE controller */
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && ((!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)) || ((PCI_FUNC(dev->devfn) == 7) && ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))))
+		return;	/* IT8172G is also more than only an IDE controller and also
+		           gives alias response for the IDE controller on func 7 */
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
+		return;	/* UM8886A/BF pair */
+	else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
+		hpt366_device_order_fixup(dev, d);
+	else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+		if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
+			printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
+			       d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
+		else
+			printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+		ide_setup_pci_device(dev, d);
+	}
+}
+
+void __init ide_scan_pcibus (int scan_direction)
+{
+	struct pci_dev *dev;
+
+	if (!scan_direction) {
+		pci_for_each_dev(dev) {
+			ide_scan_pcidev(dev);
+		}
+	} else {
+		pci_for_each_dev_reverse(dev) {
+			ide_scan_pcidev(dev);
+		}
+	}
+}
diff -Naur linux-2.6.0-test10/drivers/mtd/maps/Kconfig linux-2.6.0-test10-obs266/drivers/mtd/maps/Kconfig
--- linux-2.6.0-test10/drivers/mtd/maps/Kconfig	Mon Nov 24 10:33:21 2003
+++ linux-2.6.0-test10-obs266/drivers/mtd/maps/Kconfig	Wed Nov 26 18:31:24 2003
@@ -304,7 +304,7 @@
 
 config MTD_REDWOOD
 	tristate "CFI Flash devices mapped on IBM Redwood"
-	depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
+	depends on MTD_CFI && PPC32 && 4xx && 40x && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || OPENBLOCKS266 )
 	help
 	  This enables access routines for the flash chips on the IBM
 	  Redwood board. If you have one of these boards and would like to
diff -Naur linux-2.6.0-test10/drivers/mtd/maps/redwood.c linux-2.6.0-test10-obs266/drivers/mtd/maps/redwood.c
--- linux-2.6.0-test10/drivers/mtd/maps/redwood.c	Mon Nov 24 10:32:33 2003
+++ linux-2.6.0-test10-obs266/drivers/mtd/maps/redwood.c	Wed Nov 26 18:37:34 2003
@@ -26,7 +26,7 @@
 
 #include <asm/io.h>
 
-#if !defined (CONFIG_REDWOOD_6)
+#if !defined (CONFIG_REDWOOD_6) && !defined(CONFIG_OPENBLOCKS266)
 
 #define WINDOW_ADDR 0xffc00000
 #define WINDOW_SIZE 0x00400000
@@ -78,6 +78,7 @@
 #define WINDOW_ADDR 0xff800000
 #define WINDOW_SIZE 0x00800000
 
+#ifdef CONFIG_REDWOOD_6
 #define RW_PART0_OF	0
 #define RW_PART0_SZ	0x400000	/* 4 MiB data */
 #define RW_PART1_OF	RW_PART0_OF + RW_PART0_SZ 
@@ -111,7 +112,47 @@
 		.mask_flags = MTD_WRITEABLE	/* force read-only */
 	}
 };
-
+#else /* CONFIG_REDWOOD_6 */
+#define RW_CONF_OF	0
+#define RW_CONF_SZ	0x10000		/*64Kb Variable data*/
+#define RW_BIOS_OF	0x7c0000	/* BIOS area */
+#define RW_BIOS_SZ	0x40000
+#define RW_KERN_OF	(RW_CONF_OF)+(RW_CONF_SZ)
+#if defined(CONFIG_OPENBLOCKS_MAXKERNSIZE) && (CONFIG_OPENBLOCKS_MAXKERNSIZE != 0)
+#define RW_KERN_SZ	CONFIG_OPENBLOCKS_MAXKERNSIZE
+#else
+#define RW_KERN_SZ	(RW_BIOS_OF) - (RW_KERN_OF)
+#endif
+#define RW_USER_OF	(RW_KERN_OF) + (RW_KERN_SZ)
+#define RW_USER_SZ	(RW_BIOS_OF) - (RW_USER_OF)
+static struct mtd_partition redwood_flash_partitions[] = {
+	{
+		name: "OpenBlockS Configuration Data",
+		offset: RW_CONF_OF,
+		size: RW_CONF_SZ
+	},
+	{
+		name: "OpenBlockS Boot Image",
+		offset: RW_KERN_OF,
+		size: RW_KERN_SZ
+	},
+	{
+		name: "OpenBlockS OpenBIOS",
+		offset: RW_BIOS_OF,
+		size: RW_BIOS_SZ,
+		mask_flags: MTD_WRITEABLE       /* force read-only */
+	},
+#if  (RW_USER_SZ > 0)
+	{
+		name: "OpenBlockS User Flash",
+		offset: RW_USER_OF,
+		size: RW_USER_SZ,
+	}
+#elif (RW_USER_SZ < 0)
+#error  "Kernel Size Invalid"
+#endif
+};
+#endif
 #endif /* CONFIG_REDWOOD_6 */
 
 struct map_info redwood_flash_map = {
diff -Naur linux-2.6.0-test10/drivers/net/tulip/tulip.h linux-2.6.0-test10-obs266/drivers/net/tulip/tulip.h
--- linux-2.6.0-test10/drivers/net/tulip/tulip.h	Mon Nov 24 10:33:15 2003
+++ linux-2.6.0-test10-obs266/drivers/net/tulip/tulip.h	Wed Nov 26 17:49:17 2003
@@ -322,6 +322,10 @@
 
 struct ring_info {
 	struct sk_buff	*skb;
+#ifdef CONFIG_OPENBLOCKS266 
+  char *bounce_buffer;
+  size_t bb_size;
+#endif
 	dma_addr_t	mapping;
 };
 
diff -Naur linux-2.6.0-test10/drivers/net/tulip/tulip_core.c linux-2.6.0-test10-obs266/drivers/net/tulip/tulip_core.c
--- linux-2.6.0-test10/drivers/net/tulip/tulip_core.c	Mon Nov 24 10:32:08 2003
+++ linux-2.6.0-test10-obs266/drivers/net/tulip/tulip_core.c	Wed Nov 26 17:49:17 2003
@@ -643,6 +643,10 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		tp->tx_buffers[i].skb = NULL;
 		tp->tx_buffers[i].mapping = 0;
+#ifdef CONFIG_OPENBLOCKS266
+		tp->tx_buffers[i].bounce_buffer = NULL;
+		tp->tx_buffers[i].bb_size = 0;
+#endif
 		tp->tx_ring[i].status = 0x00000000;
 		tp->tx_ring[i].buffer2 = cpu_to_le32(tp->tx_ring_dma + sizeof(struct tulip_tx_desc) * (i + 1));
 	}
@@ -663,8 +667,28 @@
 	entry = tp->cur_tx % TX_RING_SIZE;
 
 	tp->tx_buffers[entry].skb = skb;
+#ifdef CONFIG_OPENBLOCKS266
+	{
+	  /*realloc bounce buffer*/
+	  u32 ptr; /*XXX I want to use uintptr_t */
+	  if(tp->tx_buffers[entry].bb_size < skb->len){ 
+	    tp->tx_buffers[entry].bb_size = skb->len;
+	    if(tp->tx_buffers[entry].bounce_buffer)
+	      kfree(tp->tx_buffers[entry].bounce_buffer);
+	    tp->tx_buffers[entry].bounce_buffer = kmalloc(skb->len+3,
+							  GFP_ATOMIC);
+	  }
+	  /*Align 4 byte boundary*/
+	  ptr = (u32)tp->tx_buffers[entry].bounce_buffer + 3;
+	  ptr &= ~3;
+	  
+	  memcpy((void *)ptr, skb->data, skb->len);
+	  mapping = pci_map_single(tp->pdev, (void *)ptr, skb->len, PCI_DMA_TODEVICE);
+	}
+#else
 	mapping = pci_map_single(tp->pdev, skb->data,
 				 skb->len, PCI_DMA_TODEVICE);
+#endif
 	tp->tx_buffers[entry].mapping = mapping;
 	tp->tx_ring[entry].buffer1 = cpu_to_le32(mapping);
 
diff -Naur linux-2.6.0-test10/include/asm-ppc/ibm4xx.h linux-2.6.0-test10-obs266/include/asm-ppc/ibm4xx.h
--- linux-2.6.0-test10/include/asm-ppc/ibm4xx.h	Mon Nov 24 10:31:57 2003
+++ linux-2.6.0-test10-obs266/include/asm-ppc/ibm4xx.h	Wed Nov 26 19:12:58 2003
@@ -50,6 +50,10 @@
 #include <platforms/4xx/walnut.h>
 #endif
 
+#if defined(CONFIG_OPENBLOCKS266)
+#include <platforms/4xx/openblocks266.h>
+#endif
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -92,13 +96,5 @@
 
 #endif /* CONFIG_40x */
 
-#ifndef __ASSEMBLY__
-/*
- * The "residual" board information structure the boot loader passes
- * into the kernel.
- */
-extern bd_t __res;
-#endif
-
 #endif /* __ASM_IBM4XX_H__ */
 #endif /* __KERNEL__ */
diff -Naur linux-2.6.0-test10/include/asm-ppc/ocp.h linux-2.6.0-test10-obs266/include/asm-ppc/ocp.h
--- linux-2.6.0-test10/include/asm-ppc/ocp.h	Mon Nov 24 10:31:25 2003
+++ linux-2.6.0-test10-obs266/include/asm-ppc/ocp.h	Thu Nov 27 02:20:40 2003
@@ -49,11 +49,17 @@
 #define DBG(x...)
 #endif
 
+#define OCP_MAX_IRQS    7
+#define MAX_EMACS       4
+#define MAX_OCP_DEVS    20
+#define OCP_ACTIVE      1
+#define OCP_INACTIVE    2
 #define OCP_IRQ_NA	-1	/* used when ocp device does not have an irq */
 #define OCP_IRQ_MUL	-2	/* used for ocp devices with multiple irqs */
 #define OCP_NULL_TYPE	0	/* used to mark end of list */
 #define OCP_DEV_NA	-1
 #define OCP_CPM_NA	0	/* No Clock or Power Management avaliable */
+#define EMACS_PER_ZMII  4
 
 #define OCP_ANY_ID	(~0)
 
@@ -73,6 +79,13 @@
 	char desc[50];
 };
 
+struct irq_resources {
+	char irq_name[16];
+	u16 irq;
+	void *irq_handler;
+	int flags;
+};
+
 struct ocp_def {
 	unsigned int vendor;
 	unsigned int device;
@@ -90,6 +103,7 @@
 	unsigned int vendor;
 	unsigned int device;
 	phys_addr_t paddr;
+	void *vaddr;
 	int irq;
 	unsigned long pm;
 	void *ocpdev;		/* driver data for this device */
diff -Naur linux-2.6.0-test10/include/asm-ppc/pgtable.h linux-2.6.0-test10-obs266/include/asm-ppc/pgtable.h
--- linux-2.6.0-test10/include/asm-ppc/pgtable.h	Mon Nov 24 10:31:25 2003
+++ linux-2.6.0-test10-obs266/include/asm-ppc/pgtable.h	Wed Nov 26 18:42:00 2003
@@ -609,11 +609,19 @@
  * must not include the _PAGE_PRESENT bit, the _PAGE_FILE bit, or the
  *_PAGE_HASHPTE bit (if used).  -- paulus
  */
+#ifdef CONFIG_OPENBLOCKS266
+#define __swp_type(entry)		((entry).val & 0x3f)
+#define __swp_offset(entry)		((entry).val >> 10)
+#define __swp_entry(type, offset)	((swp_entry_t) { (type) | ((offset) << 10) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 2 })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val << 2 })
+#else
 #define __swp_type(entry)		((entry).val & 0x1f)
 #define __swp_offset(entry)		((entry).val >> 5)
 #define __swp_entry(type, offset)	((swp_entry_t) { (type) | ((offset) << 5) })
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 3 })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val << 3 })
+#endif
 
 /* Encode and decode a nonlinear file mapping entry */
 #define PTE_FILE_MAX_BITS	29
diff -Naur linux-2.6.0-test10/include/asm-ppc/pushsw.h linux-2.6.0-test10-obs266/include/asm-ppc/pushsw.h
--- linux-2.6.0-test10/include/asm-ppc/pushsw.h	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/include/asm-ppc/pushsw.h	Wed Nov 26 17:49:17 2003
@@ -0,0 +1,19 @@
+/* 
+ *	Century <www.centurysys.co.jp>
+ *		- Century's push switch driver header
+ */
+
+#include <linux/ioctl.h>
+#include <linux/major.h>
+/* #include <linux/miscdevice.h> */
+
+#define PUSHSW_MAJOR		(MISC_MAJOR)
+
+#define	PUSHSW_IOCTL_BASE	'P'
+
+#define	PSWIOC_GETSTATUS	_IOR(PUSHSW_IOCTL_BASE, 0, int)
+#define	PSWIOC_WAITPUSH		_IOR(PUSHSW_IOCTL_BASE, 1, int)
+#define	PSWIOC_GETWAITPID	_IOR(PUSHSW_IOCTL_BASE, 2, int)
+
+#define PSWIOF_PUSHED		(1)
+#define PSWIOF_NOTPUSHED	(0)
diff -Naur linux-2.6.0-test10/include/linux/i2c.h linux-2.6.0-test10-obs266/include/linux/i2c.h
--- linux-2.6.0-test10/include/linux/i2c.h	Mon Nov 24 10:31:14 2003
+++ linux-2.6.0-test10-obs266/include/linux/i2c.h	Thu Nov 27 03:00:50 2003
@@ -161,6 +161,7 @@
 	  alignment considerations */
 	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
 	struct i2c_driver *driver;	/* and our access routines	*/
+	void *data;			/* for the clients		*/
 	int usage_count;		/* How many accesses currently  */
 					/* to the client		*/
 	struct device dev;		/* the device structure		*/
@@ -234,6 +235,11 @@
 	int (*client_register)(struct i2c_client *);
 	int (*client_unregister)(struct i2c_client *);
 
+        void *data;	/* private data for the adapter                 */
+			/* some data fields that are used by all types  */
+			/* these data fields are readonly to the public */
+			/* and can be set via the i2c_ioctl call        */
+
 	/* data fields that are valid for all devices	*/
 	struct semaphore bus_lock;
 	struct semaphore clist_lock;
diff -Naur linux-2.6.0-test10/include/linux/ibm_ocp_gpio.h linux-2.6.0-test10-obs266/include/linux/ibm_ocp_gpio.h
--- linux-2.6.0-test10/include/linux/ibm_ocp_gpio.h	Thu Jan  1 09:00:00 1970
+++ linux-2.6.0-test10-obs266/include/linux/ibm_ocp_gpio.h	Wed Nov 26 20:39:36 2003
@@ -0,0 +1,58 @@
+/*
+ * FILE NAME ibm_ocp_gpio.h
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Generic gpio.
+ *
+ *  Armin Kuster akuster@pacbell.net
+ *  Sept, 2001
+ *
+ *  Orignial driver
+ *  Author: MontaVista Software, Inc.  <source@mvista.com>
+ *          Frank Rowand <frank_rowand@mvista.com>
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IBM_OCP_GPIO_H
+#define __IBM_OCP_GPIO_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define IBMGPIO_IOCTL_BASE	'Z'
+
+struct ibm_gpio_ioctl_data {
+	__u32 device;
+	__u32 mask;
+	__u32 data;
+};
+
+#define GPIO_MINOR             185
+#define IBMGPIO_IN		_IOWR(IBMGPIO_IOCTL_BASE, 0, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OUT		_IOW (IBMGPIO_IOCTL_BASE, 1, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_OPEN_DRAIN	_IOW (IBMGPIO_IOCTL_BASE, 2, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_TRISTATE	_IOW (IBMGPIO_IOCTL_BASE, 3, struct ibm_gpio_ioctl_data)
+#define IBMGPIO_CFG		_IOW (IBMGPIO_IOCTL_BASE, 4, struct ibm_gpio_ioctl_data)
+
+#endif
diff -Naur linux-2.6.0-test10/init/main.c linux-2.6.0-test10-obs266/init/main.c
--- linux-2.6.0-test10/init/main.c	Mon Nov 24 10:31:14 2003
+++ linux-2.6.0-test10-obs266/init/main.c	Thu Nov 27 01:41:27 2003
@@ -114,6 +114,10 @@
 /* Setup configured maximum number of CPUs to activate */
 static unsigned int max_cpus = NR_CPUS;
 
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+extern int obsled_out(int);
+#endif
+
 /*
  * Setup routine for controlling SMP activation
  *
@@ -393,6 +397,9 @@
  * enable them
  */
 	lock_kernel();
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	obsled_out(2);
+#endif
 	printk(linux_banner);
 	setup_arch(&command_line);
 	setup_per_zone_pages_min();
@@ -560,6 +567,9 @@
 static int init(void * unused)
 {
 	lock_kernel();
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	obsled_out(3);
+#endif
 	/*
 	 * Tell the world that we're going to be the grim
 	 * reaper of innocent orphaned children.
@@ -579,6 +589,9 @@
 	do_basic_setup();
 
 	prepare_namespace();
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	obsled_out(5);
+#endif
 
 	/*
 	 * Ok, we have completed the initial bootup, and
@@ -602,6 +615,9 @@
 	 * trying to recover a really broken machine.
 	 */
 
+#if defined(CONFIG_OPENBLOCKS266) && defined(CONFIG_OBS_LED)
+	obsled_out(6);
+#endif
 	if (execute_command)
 		run_init_process(execute_command);
 
