diff -urN -X /home/arm/dontdiff_tml_arm /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/pcmcia/psion_etna.c linux-2.4.19-rmk2/drivers/pcmcia/psion_etna.c
diff -urN -X /home/arm/dontdiff_tml_arm /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/pcmcia/psion_etna.c linux-2.4.19-rmk2/drivers/pcmcia/psion_etna.c
--- /home/download/kernels/linux-2.4.19-rmk2-vanilla/drivers/pcmcia/psion_etna.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.19-rmk2/drivers/pcmcia/psion_etna.c	2002-10-02 22:07:30.000000000 -0700
@@ -0,0 +1,650 @@
+/*
+ * psion_etna.c - Psion-specific PCMCIA functions
+ * 
+ * Copyright (C) 2001 Tony Lindgren <tony@atomide.com>
+ * Copyright (C) 2001 Shane Nay <shane@place.org>
+ * 
+ * Contains code from the clps6700 driver for linux,
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * Contains code from the Psion 5 ETNA driver for linux, 
+ * Copyright (C) 1999 Werner Almesberger.
+ *
+ * This driver is currently a big mess, so a rewrite is needed.
+ * But, it works, so we'll clean it up later.
+ *
+ * ETNA only has one interrupt that is shared with the card and
+ * the socket. The ETNA interrupt handler schedules a socket
+ * interrupt only if the interrupt is not a card interrupt.
+ * See irq.c on the ETNA interrupt handler.
+ *
+ * The code is currently all over the place. See also ide.h and
+ * irq.c.
+ *
+ * Psion is configured to trigger IRQ_MCINT with the CF card door
+ * switch. Epoc uses this, we don't.
+ *
+ * The various ETNA registers are not fully deciphered, mostly
+ * just working Epoc values are written to the registers without
+ * really knowing what they do.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+
+#include <asm/hardware/psionw.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/bus_ops.h>
+
+#include "psion_etna.h"
+
+MODULE_AUTHOR("Tony Lindgren");
+MODULE_DESCRIPTION("PSION ETNA PCMCIA socket driver");
+
+#define NR_ETNA		1
+
+static u8 cur_cfg = 0x1;	/* Current card configuration */
+static u8 initialized;
+
+struct etna_skt {
+	u_int			nr;
+	u_int			physbase;
+	u_int			regbase;
+	u_int			pmr;
+	u_int			cpcr;
+	u_int			cpcr_3v3;
+	u_int			cpcr_5v0;
+	u_int			cur_pmr;
+	u_int			cur_cicr;
+	u_int			cur_pcimr;
+	u_int			cur_cpcr;
+	void			(*handler)(void *, u_int);
+	void			*handler_info;
+
+	u_int			ev_pending;
+	spinlock_t		ev_lock;
+};
+
+static struct etna_skt *skts[NR_ETNA];
+
+static int etna_sock_init(u_int sock)
+{
+	struct etna_skt *skt = skts[sock];
+
+	skt->cur_cicr  = 0;		/* PC card interface config reg */
+	skt->cur_pmr   = skt->pmr;	/* Power mgmt reg */
+	skt->cur_pcimr = 0;		/* PC card mask reg */
+	skt->cur_cpcr  = skt->cpcr;	/* Card power ctrl reg */
+
+	DEBUG_ETNA("ETNA skt%d: sock_init()\n", sock);
+	return 0;
+}
+
+static int etna_suspend(u_int sock)
+{
+	DEBUG_ETNA("ETNA: etna_suspend\n");
+	etna_powerdown(1);
+	return 0;
+}
+
+static int etna_register_callback(u_int sock, void (*handler)(void *, u_int), 
+				  void *info)
+{
+	struct etna_skt *skt = skts[sock];
+
+	DEBUG_ETNA("ETNA: skt%d: register_callback: %p (%p)\n", sock, handler, info);
+	skt->handler_info = info;
+	skt->handler = handler;
+
+	return 0;
+} 
+
+static int etna_inquire_socket(u_int sock, socket_cap_t *cap)
+{
+
+	DEBUG_ETNA("ETNA: etna_inquire_socket\n");
+
+#if 0
+	/* Leaving out SS_CAP_SATIC_MAP makes the card detection not to work*/
+	cap->features = (SS_CAP_PAGE_REGS | SS_CAP_PCCARD | 
+		SS_CAP_STATIC_MAP);
+#endif
+
+	cap->features = (SS_CAP_PAGE_REGS | SS_CAP_PCCARD | 
+		SS_CAP_STATIC_MAP | SS_CAP_MEM_ALIGN);
+
+	cap->irq_mask  = 0;
+	cap->map_size  = PAGE_SIZE;
+        cap->pci_irq   = IRQ_EINT1;
+	cap->cb_dev    = NULL;
+	cap->bus       = NULL;
+	cap->io_offset = 0;
+
+	return 0;
+}
+
+
+static int __etna_get_status(struct etna_skt *skt)
+{
+	unsigned int etna_state = 0;
+	int cardint, status, sktpower;
+
+	DEBUG_ETNA("ETNA: __etna_get_status\n");
+
+	etna_state = (SS_DETECT | SS_READY);
+
+	sktpower = etna_readb(ETNA_SKT_ACTIVE);
+	status = etna_readb(ETNA_SKT_STATUS);
+
+	// Check if there is a card in the socket
+	if (status & SKT_CARD_OUT) {
+		DEBUG_ETNA("ETNA: Int: Card is not inserted: 0x%02x\n", status);
+		etna_state &= ~SS_DETECT;
+		etna_state &= ~SS_READY;
+	}
+
+	// Check that the card has power if in socket
+	if (!sktpower) {
+		DEBUG_ETNA("ETNA: Int: No socket power\n");
+		etna_state &= ~SS_READY;
+		etna_powerup();
+	}
+
+	// Test for socket ready
+	if ( (status & SKT_BUSY) || (status & SKT_NOT_READY) ) {
+		DEBUG_ETNA("ETNA: Int: Socket busy or not ready: 0x%02x\n", status);
+		etna_state &= ~SS_READY;
+	}
+
+	/* Force some unknown values ready */
+	etna_state &= ~SS_BATWARN;
+	etna_state &= ~SS_BATDEAD;
+	etna_state &= ~SS_XVCARD;
+	etna_state |= SS_3VCARD;
+	
+	// Clear pending status. What sets this on?
+	etna_state &= ~SS_PENDING;
+
+	DEBUG_ETNA("ETNA: Status: skt%d: status: %08x -> %s %s %s %s %s %s)\n",
+		skt->nr, status,
+	        etna_state & SS_READY   ? "rdy" : "---",
+	        etna_state & SS_DETECT  ? "det" : "---",
+	        etna_state & SS_BATWARN ? "bw"  : "--",
+		etna_state & SS_BATDEAD ? "bd"  : "--",
+		etna_state & SS_3VCARD  ? "3v"  : "--",
+		etna_state & SS_XVCARD  ? "xv"  : "--");
+
+	return etna_state;
+}
+
+static int etna_get_status(u_int sock, u_int *valp)
+{
+	struct etna_skt *skt = skts[sock];
+	*valp = __etna_get_status(skt);
+	return 0; /* not used! */
+}
+
+static int etna_get_socket(u_int sock, socket_state_t *state)
+{
+	DEBUG_ETNA("ETNA: etna_get_socket\n");
+	return -EINVAL;
+}
+
+static int etna_set_socket(u_int sock, socket_state_t *state)
+{
+	struct etna_skt *skt = skts[sock];
+	unsigned long flags;
+	u_int cpcr = skt->cur_cpcr, pmr = skt->cur_pmr, cicr = skt->cur_cicr;
+	u_int pcimr = 0;
+	DEBUG_ETNA("ETNA: etna_set_socket with sock=%d\n", sock);
+
+	if (state->flags & SS_RESET) {
+		DEBUG_ETNA("ETNA Socket: SS_RESET\n");
+	} else if (state->flags & SS_OUTPUT_ENA) {
+		DEBUG_ETNA("ETNA Socket: SS_OUTPUT_ENA\n");
+	}
+
+	if (state->flags & SS_IOCARD) {
+		DEBUG_ETNA("ETNA Socket: SS_IOCARD\n");
+	} else {
+		if (state->csc_mask & SS_BATDEAD) {
+			DEBUG_ETNA("ETNA Socket: SS_BATDEAD\n");
+			pcimr = 0;
+		}
+		if (state->csc_mask & SS_BATWARN) {
+			DEBUG_ETNA("ETNA Socket: SS_BATWARN\n");
+			pcimr = 0;
+		}
+		if (state->csc_mask & SS_READY) {
+			DEBUG_ETNA("ETNA Socket: SS_READY\n");
+			pcimr = 0x41;
+		}
+	}
+
+	if (state->csc_mask & SS_DETECT) {
+		DEBUG_ETNA("ETNA Socket: SS_DETECT\n");
+		pcimr = 0x41;
+	}
+
+	switch (state->Vcc) {
+	case 0:				break;
+	case 33: cpcr |= skt->cpcr_3v3; break;
+	case 50: cpcr |= skt->cpcr_5v0; break;
+	default: return -EINVAL;
+	}
+
+	DEBUG_ETNA("skt%d: PMR: %04x, CPCR: %04x, CICR: %04x PCIMR: %04x "
+		"(Vcc = %d, flags = %c%c%c%c, csc = %c%c%c%c%c)\n",
+		sock, pmr, cpcr, cicr, pcimr, state->Vcc,
+		state->flags & SS_RESET      ? 'r' : '-',
+		state->flags & SS_PWR_AUTO   ? 'p' : '-',
+		state->flags & SS_IOCARD     ? 'i' : '-',
+		state->flags & SS_OUTPUT_ENA ? 'o' : '-',
+		state->csc_mask & SS_STSCHG  ? 's' : '-',
+		state->csc_mask & SS_BATDEAD ? 'd' : '-',
+		state->csc_mask & SS_BATWARN ? 'w' : '-',
+		state->csc_mask & SS_READY   ? 'r' : '-',
+		state->csc_mask & SS_DETECT  ? 'c' : '-');
+
+	save_flags_cli(flags);
+
+	if (skt->cur_cpcr != cpcr) {
+		skt->cur_cpcr = cpcr;
+		//__raw_writel(skt->cur_cpcr, skt->regbase + CPCR);
+	}
+
+	if (skt->cur_pmr != pmr) {
+		skt->cur_pmr = pmr;
+		//__raw_writel(skt->cur_pmr, skt->regbase + PMR);
+	}
+
+	/* Enable card interrutps */
+	if (skt->cur_pcimr != pcimr) {
+		skt->cur_pcimr = pcimr;
+		__raw_writeb(skt->cur_pcimr, skt->regbase + PCIMR);
+	}
+	if (skt->cur_cicr != cicr) {
+		skt->cur_cicr = cicr;
+		//__raw_writel(skt->cur_cicr, skt->regbase + CICR);
+	}
+
+	restore_flags(flags);
+
+	return 0;
+}
+
+static int etna_get_io_map(u_int sock, struct pccard_io_map *io)
+{
+	return -EINVAL;
+}
+
+static int etna_set_io_map(u_int sock, struct pccard_io_map *map)
+{
+
+	unsigned long start;
+
+	DEBUG_ETNA("ETNA: etna_set_io_map\n");
+	
+	DEBUG_ETNA("ETNA: card speed: %u\n", map->speed);
+
+	start=map->start;
+	if(map->stop==1)
+		map->stop=PAGE_SIZE-1;
+
+	map->start = CF1_V_BASE;
+	map->stop=map->start+(map->stop-start);
+
+	return 0;
+}
+
+static int etna_get_mem_map(u_int sock, struct pccard_mem_map *mem)
+{
+	DEBUG_ETNA("ETNA: etna_get_mem_map\n");
+	return -EINVAL;
+}
+
+/*
+ * Set the memory map attributes for this socket.  (ie, mem->speed)
+ * Note that since we have SS_CAP_STATIC_MAP set, we don't need to do
+ * any mapping here at all; we just need to return the address (suitable
+ * for ioremap) to map the requested space in mem->sys_start.
+ *
+ * flags & MAP_ATTRIB indicates whether we want attribute space.
+ */
+static int etna_set_mem_map(u_int sock, struct pccard_mem_map *mem)
+{
+	struct etna_skt *skt = skts[sock];
+	u_int off;
+	unsigned long start;
+
+	start = mem->sys_start;
+	if(mem->sys_stop==0)
+		mem->sys_stop=PAGE_SIZE-1;
+
+	// Only CF_ATTR_BASE 0x00000000 makes dump_cis work
+	if (mem->flags & MAP_ATTRIB)
+		off = CF_ATTR_BASE;
+	else
+		off = CF_MEM_BASE;	/* This may not be right */	
+	
+	mem->sys_start  = skt->physbase + off;
+	mem->sys_start += mem->card_start;
+
+	////mem->sys_stop=mem->sys_start+(mem->sys_stop-start);
+
+	return 0;
+}
+
+static void etna_proc_setup(u_int sock, struct proc_dir_entry *base)
+{
+}
+
+static struct pccard_operations etna_operations = {
+	init:			etna_sock_init,
+	suspend:		etna_suspend,
+	register_callback:	etna_register_callback,
+	inquire_socket:		etna_inquire_socket,
+	get_status:		etna_get_status,
+	get_socket:		etna_get_socket,
+	set_socket:		etna_set_socket,
+	get_io_map:		etna_get_io_map,
+	set_io_map:		etna_set_io_map,
+	get_mem_map:		etna_get_mem_map,
+	set_mem_map:		etna_set_mem_map,
+	proc_setup:		etna_proc_setup
+};
+
+static void etna_bh(void *dummy)
+{
+	int i;
+
+	DEBUG_ETNA("ETNA: etna_bh\n");
+	for (i = 0; i < NR_ETNA; i++) {
+		struct etna_skt *skt = skts[i];
+		unsigned long flags;
+		u_int events;
+
+		if (!skt)
+			continue;
+
+		/*
+		 * Note!  We must read the pending event state
+		 * with interrupts disabled, otherwise we race
+		 * with our own interrupt routine!
+		 */
+		spin_lock_irqsave(&skt->ev_lock, flags);
+		events = skt->ev_pending;
+		skt->ev_pending = 0;
+		spin_unlock_irqrestore(&skt->ev_lock, flags);	
+
+		if (skt->handler && events)
+			skt->handler(skt->handler_info, events);
+	}
+}
+
+static struct tq_struct etna_task = {
+	routine:	etna_bh
+};
+
+/*
+ * Handles card insert and eject.
+ * Scheduled from mask_etna_irq, as there seems to be only
+ * one interrupt for ETNA and the CF card.
+ */
+void etna_interrupt(void)
+{
+	struct etna_skt *skt = skts[0];
+	int status, sktpower, cardpower;
+	int events;
+
+	DEBUG_ETNA("ETNA: etna_interrupt\n");
+
+	/* We may get called from ide init */
+	if (!initialized) {
+		return;
+	}
+
+	events = __etna_get_status(skt);
+
+	if ( (events & SS_DETECT) && (events & SS_READY) ) {
+		DEBUG_ETNA("ETNA: Int: Nothing to do, returning\n");
+		return;
+	}
+
+	spin_lock(&skt->ev_lock);
+	skt->ev_pending |= events;
+	spin_unlock(&skt->ev_lock);
+	schedule_task(&etna_task);
+}
+
+
+static int __init etna_init_skt(int nr)
+{
+	struct etna_skt *skt;
+
+	DEBUG_ETNA("ETNA: etna_init_skt\n");
+	skt = kmalloc(sizeof(struct etna_skt), GFP_KERNEL);
+	if (!skt)
+		return -ENOMEM;
+
+	memset(skt, 0, sizeof(struct etna_skt));
+
+	spin_lock_init(&skt->ev_lock);
+
+	skt->nr       = nr;
+	//skt->physbase = nr ? 0x50000000 : 0x40000000;
+	skt->physbase = CF1_P_BASE;
+	DEBUG_ETNA("ETNA: skt->physbase=0x%x\n", skt->physbase);
+
+	skt->cur_pmr  = skt->pmr;
+	//skt->regbase = (u_int)__ioremap(skt->physbase + CF_REG_BASE,
+	//	CF_REG_SIZE, 0);
+	skt->regbase = ETNA_V_BASE;
+
+	if (!skt->regbase)
+	goto err_free;
+
+	skts[nr] = skt;
+	return 0;
+
+err_unmap:
+	iounmap((void *)skt->regbase);
+err_free:
+	kfree(skt);
+	skts[nr] = NULL;
+	return 1;
+}
+
+static void etna_free_resources(void)
+{
+	int i;
+
+	DEBUG_ETNA("ETNA: etna_free_resources\n");
+	for (i = NR_ETNA; i >= 0; i--) {
+		struct etna_skt *skt = skts[i];
+		skts[i] = NULL;
+		if (skt == NULL)
+			continue;
+		//free_irq(IRQ_EINT1, skt); /* Socket interrupt */
+		if (skt->regbase) {
+			__raw_writeb(0,	skt->regbase + PCIMR);	/* Card int mask */
+
+		}
+
+		//iounmap((void *)skt->regbase); /* Using ETNA_V_BASE for now */
+		kfree(skt);
+	}
+}
+
+static int __init etna_init(void)
+{
+	int err, nr;
+
+	printk("ETNA: Initializing CF controller\n");
+	
+	for (nr = 0; nr < NR_ETNA; nr++) {
+		err = etna_init_skt(nr);
+		if (err)
+			goto free;
+	}
+
+	err = register_ss_entry(nr, &etna_operations);
+	if (err)
+		goto free;
+
+
+	initialized = 1;
+	etna_powerup();
+
+	return 0;
+
+free:
+	printk("ETNA: Failed to initialize\n");
+	etna_free_resources();
+	/*
+	 * An error occurred.  Unmap and free all ETNA
+	 */
+	return err;
+}
+
+void etna_powerup(int lock)
+{
+	DEBUG_ETNA("ETNA: CompactFlash PCMCIA controller warm init\n");
+
+	/* Turn on the power if it is not already on */
+	start_pump(lock);
+	mdelay(30);	/* Needed for some cards */
+	etna_init_hw();
+
+	/* Restore the card configuration */
+	etna_set_cf(cur_cfg);
+
+	/* Clear the ETNA interrupts */
+	__raw_writeb(0x01, ETNA_V_BASE + ETNA_INT_CLEAR);
+
+	/* Turn on ETNA interrupt */
+	__raw_writeb(0x01, ETNA_V_BASE + ETNA_INT_MASK);
+
+	//enable_irq(IRQ_EINT1);
+}
+
+/*
+ * Powers down the card and ETNA.
+ * Some of these steps may not be necessary.
+ */
+void etna_powerdown(int lock)
+{
+	int cfg;
+	long flags;
+
+	DEBUG_ETNA("ETNA: Powering down the CF controller\n");
+
+	if (lock)
+		save_flags_cli(flags);
+
+	//disable_irq(IRQ_EINT1);
+
+	/* Save the current card configuration */
+	cur_cfg = CF1_READB(CF_CUR_CFG);
+
+	/* Turn off card interrupts */
+	__raw_writeb(0, ETNA_V_BASE + ETNA_INT_MASK);
+
+	/* Clear card interrupts */
+	__raw_writeb(0xff, ETNA_V_BASE + ETNA_INT_CLEAR);
+
+	/* 
+	 * Writing this makes power up fail with garbage
+	 * if something does not come up right.
+	 */
+	__raw_writeb(0, ETNA_V_BASE + ETNA_SKT_CTRL);
+
+	__raw_writeb(0, ETNA_V_BASE + ETNA_SKT_ACTIVE);
+	__raw_writeb(0, ETNA_V_BASE + ETNA_SKT_CFG);
+	__raw_writeb(0, ETNA_V_BASE + ETNA_WAKE_1);
+	__raw_writeb(0, ETNA_V_BASE + ETNA_WAKE_2);
+
+	/* Power down the CF card */
+	cfg = psionw_readb(PBDR);
+	if (!(cfg & PBDR_VPCEN)) {
+		psionw_writeb(cfg | PBDR_VPCEN, PBDR);
+	}
+
+	/* Delay is needed here */
+	mdelay(20);
+
+#if 0
+	/* Power down the ETNA socket */
+	cfg = psionw_readb(PDDR);
+	if (cfg & PDDR_ETNA_PWR) {
+		//psionw_writeb(cfg & ~PDDR_ETNA_PWR, PDDR);
+	}
+#endif
+
+	if (lock)
+		restore_flags(flags);
+}
+
+void psion_debug_etna(void)
+{
+	debug_gpio();
+
+	printk("ETNA: ATTR_BASE = 0x%08x ATTR_BASE + 4 = 0x%08x\n",
+	       CF1_READL(0),
+	       CF1_READL(4));
+
+	printk("ETNA: MEM_BASE = 0x%08x MEM_BASE + 4 = 0x%08x\n",
+	       CF1_MEM_READL(0),
+	       CF1_MEM_READL(4));
+
+	printk("ETNA: SKT_STATUS=0x%02x SKT_CFG=0x%02x SKT_CTRL=0x%02x SKT_ACTIVE=0x%02x\n",
+	       __raw_readb(ETNA_V_BASE + ETNA_SKT_STATUS),
+	       __raw_readb(ETNA_V_BASE + ETNA_SKT_CFG),
+	       __raw_readb(ETNA_V_BASE + ETNA_SKT_CTRL),
+	       __raw_readb(ETNA_V_BASE + ETNA_SKT_ACTIVE));
+
+	printk("ETNA: ETNA_INT_STATUS=0x%02x ETNA_INT_MASK=0x%02x\n",
+	       __raw_readb(ETNA_V_BASE + ETNA_INT_STATUS),
+	       __raw_readb(ETNA_V_BASE + ETNA_INT_MASK));
+
+	printk("CF1: 0x200=0x%02x 0x202=0x%02x 0x204=0x%02x\n",
+	       CF1_READB(CF_CUR_CFG),
+	       CF1_READB(0x202),
+	       CF1_READB(0x204));
+	DEBUG_CF1_REG("CFG_REG", CF_CFG_REG);
+
+	printk("MEMCFG1: 0x%08x MEMCFG2=0x%08x\n", 
+	       psionw_readl(MEMCFG1), psionw_readl(MEMCFG2));
+
+	printk("CF1 READ TEST: 0x%x\n",
+	       CF1_INB(0x3f6));
+}
+
+static void __exit etna_exit(void)
+{
+	unregister_ss_entry(&etna_operations);
+	etna_free_resources();
+}
+
+module_init(etna_init);
+module_exit(etna_exit);
