Subject: patch for 2.6.14-rc1 for pcmcia on swarm

From: Peter 'p2' De Schrijver <[email-masked]>
Date: Fri, 23 Sep 2005 02:35:03 +0200

diff -urN -x asm -x scripts -x config linux/drivers/ide/legacy/ide-cs.c linux-my/drivers/ide/legacy/ide-cs.c
--- linux/drivers/ide/legacy/ide-cs.c	2005-09-15 10:54:18.000000000 +0200
+++ linux-my/drivers/ide/legacy/ide-cs.c	2005-09-22 18:06:17.000000000 +0200
@@ -186,10 +186,19 @@
 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq)
 {
     hw_regs_t hw;
+
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+	extern int sb_pcmcia_ack_intr(struct hwif_s *hwif);
+#endif
+
     memset(&hw, 0, sizeof(hw));
     ide_init_hwif_ports(&hw, io, ctl, NULL);
     hw.irq = irq;
     hw.chipset = ide_pci;
+
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+    hw.ack_intr=sb_pcmcia_ack_intr;
+#endif
     return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
 }
 
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/Kconfig linux-my/drivers/pcmcia/Kconfig
--- linux/drivers/pcmcia/Kconfig	2005-09-15 10:54:58.000000000 +0200
+++ linux-my/drivers/pcmcia/Kconfig	2005-09-22 16:50:27.000000000 +0200
@@ -221,6 +221,10 @@
 	tristate "NEC VRC4173 CARDU support"
 	depends on CPU_VR41XX && PCI && PCMCIA
 
+config PCMCIA_SIBYTE_SB1xxx_SOC
+        tristate "SiByte SB1xxxx PCMCIA support"
+        depends on PCMCIA && SIBYTE_SB1xxx_SOC
+
 config OMAP_CF
 	tristate "OMAP CompactFlash Controller"
 	depends on PCMCIA && ARCH_OMAP16XX
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/Makefile linux-my/drivers/pcmcia/Makefile
--- linux/drivers/pcmcia/Makefile	2005-09-17 02:38:10.000000000 +0200
+++ linux-my/drivers/pcmcia/Makefile	2005-09-22 16:50:43.000000000 +0200
@@ -35,6 +35,8 @@
 obj-$(CONFIG_PCMCIA_VRC4171)			+= vrc4171_card.o
 obj-$(CONFIG_PCMCIA_VRC4173)			+= vrc4173_cardu.o
 obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
+obj-$(CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC)          += sibyte_generic.o
+
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/pcmcia_resource.c linux-my/drivers/pcmcia/pcmcia_resource.c
--- linux/drivers/pcmcia/pcmcia_resource.c	2005-09-15 10:54:58.000000000 +0200
+++ linux-my/drivers/pcmcia/pcmcia_resource.c	2005-09-22 17:26:24.000000000 +0200
@@ -648,6 +648,7 @@
 		c->Copy = req->Copy;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
 	}
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
 	if (req->Present & PRESENT_OPTION) {
 		if (s->functions == 1) {
 			c->Option = req->ConfigIndex & COR_CONFIG_MASK;
@@ -663,6 +664,7 @@
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
 		mdelay(40);
 	}
+#endif
 	if (req->Present & PRESENT_STATUS) {
 		c->Status = req->Status;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/sibyte_generic.c linux-my/drivers/pcmcia/sibyte_generic.c
--- linux/drivers/pcmcia/sibyte_generic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-my/drivers/pcmcia/sibyte_generic.c	2005-09-22 16:56:24.000000000 +0200
@@ -0,0 +1,558 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#include <linux/ide.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <asm/sibyte/board.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_genbus.h>
+
+#define IO_MAP_SIZE	0x1000
+
+#define CARDPRESENT(s) (((s) & (M_PCMCIA_STATUS_CD1 | \
+			M_PCMCIA_STATUS_CD2)) == 0)
+
+#define POWERON(s)	((s) & (M_PCMCIA_STATUS_3VEN | \
+			M_PCMCIA_STATUS_5VEN))
+
+#define SIBYTE_PCMCIA_POLL_PERIOD (2*HZ)
+
+DECLARE_MUTEX(pcmcia_sockets_lock);
+
+struct sibyte_pcmcia_socket {
+	struct pcmcia_socket socket;
+
+	struct device *dev;
+	int irq;
+
+	int status;
+	socket_state_t cs_state;
+
+	unsigned short	spd_io[MAX_IO_WIN];
+	unsigned short	spd_mem[MAX_WIN];
+
+	struct resource	res_skt;
+	struct resource	res_io;
+	struct resource	res_mem;
+
+	void *virt_io;
+	ioaddr_t phys_io;
+	unsigned int phys_mem;
+	unsigned short	speed_io, speed_attr, speed_mem;
+
+	unsigned int irq_state;
+
+	struct timer_list       poll_timer;
+
+};
+
+struct sibyte_pcmcia_socket sibyte_pcmcia_socket[1];
+#define PCMCIA_SOCKET(x) (sibyte_pcmcia_socket+x);
+
+static unsigned int sibyte_pcmcia_skt_state(struct sibyte_pcmcia_socket *skt)
+{
+	u32 stat;
+	unsigned int status=0;
+
+	stat=csr_in32(IOADDR(A_IO_PCMCIA_STATUS));
+	
+
+	if(CARDPRESENT(status)) 
+		status=SS_DETECT;
+	if(!(stat & M_PCMCIA_STATUS_VS1))
+		status|=SS_3VCARD;
+	if(!(stat & M_PCMCIA_STATUS_VS2))
+		status|=SS_XVCARD;
+	if(stat & M_PCMCIA_STATUS_WP)
+		status|=SS_WRPROT;
+	if(stat & M_PCMCIA_STATUS_RDY)
+		status|=SS_READY;
+	if(stat & POWERON(status))
+		status|=SS_POWERON;
+	if(stat & (M_PCMCIA_STATUS_CDCHG | M_PCMCIA_STATUS_WPCHG | 
+		   M_PCMCIA_STATUS_RDYCHG))
+		status|=SS_STSCHG;
+
+
+	return status;
+}
+
+static DEFINE_SPINLOCK(status_lock);
+
+static void sibyte_check_status(struct sibyte_pcmcia_socket *skt)
+{
+	unsigned int events;
+
+	do {
+		unsigned int status;
+		unsigned long flags;
+
+		status=sibyte_pcmcia_skt_state(skt);
+
+		spin_lock_irqsave(&status_lock, flags);
+		events = (status ^ skt->status) & skt->cs_state.csc_mask;
+		skt->status=status;
+		spin_unlock_irqrestore(&status_lock, flags);
+
+		if(events)
+			pcmcia_parse_events(&skt->socket, events);
+	} while(events);
+}
+
+
+static void sibyte_pcmcia_poll_event(unsigned long context)
+{
+	struct sibyte_pcmcia_socket *skt=
+		(struct sibyte_pcmcia_socket *)context;
+
+	mod_timer(&skt->poll_timer, jiffies + SIBYTE_PCMCIA_POLL_PERIOD);
+
+	sibyte_check_status(skt);
+}
+
+
+static irqreturn_t sibyte_pcmcia_interrupt(int irq, void *context, 
+					   struct pt_regs *regs)
+{
+	struct sibyte_pcmcia_socket *skt=
+		(struct sibyte_pcmcia_socket *)context;
+
+	sibyte_check_status(skt);
+
+	return IRQ_HANDLED;
+}
+		
+/* Note that Vpp is never set. There are normally 2 lines to the pcmcia
+ * power controller to control the Vpp level. The SB1250 PCMCIA control register
+ * however provides only 1 bit to control Vpp. Any information on the exact
+ * behaviour welcome.
+ */
+static int sibyte_pcmcia_config_skt(struct sibyte_pcmcia_socket *skt, 
+				    socket_state_t *state)
+{
+	u32 config;
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+
+	config &= ~(M_PCMCIA_CFG_3VEN | M_PCMCIA_CFG_5VEN);
+
+	switch(state->Vcc) {
+		case 33:
+			config|=M_PCMCIA_CFG_3VEN;
+			break;
+		case 50:
+			config|=M_PCMCIA_CFG_5VEN;
+			break;
+	}
+
+	if(state->csc_mask & SS_DETECT)
+		config&=~M_PCMCIA_CFG_CDMASK;
+	else
+		config|=M_PCMCIA_CFG_CDMASK;
+
+	config &= ~M_PCMCIA_CFG_RESET;
+	if(state->flags & SS_RESET) {
+		config|=M_PCMCIA_CFG_RESET;
+	}
+
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	return 0;
+}
+
+static int sibyte_pcmcia_sock_init(struct pcmcia_socket *sock)
+{
+	return 0;
+}
+
+
+static int sibyte_pcmcia_get_status(struct pcmcia_socket *sock, 
+				    unsigned int *status)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	skt->status=sibyte_pcmcia_skt_state(skt);
+	*status=skt->status;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_get_socket(struct pcmcia_socket *sock, 
+				    socket_state_t *state)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	*state=skt->cs_state;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_set_socket(struct pcmcia_socket *sock, 
+				    socket_state_t *state)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	return sibyte_pcmcia_config_skt(skt,state);
+}
+
+static int sibyte_pcmcia_set_io_map(struct pcmcia_socket *sock, 
+			     	    struct pccard_io_map *io)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+	unsigned int speed;
+	u32 config;
+
+	if (io->map >= MAX_IO_WIN) {
+		return -1;
+	}
+
+	if (io->flags & MAP_ACTIVE) {
+		speed=(io->speed > 0) ? io->speed : 255;
+		skt->spd_io[io->map]=speed;
+	}
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+        config&=~M_PCMCIA_CFG_ATTRMEM;
+        csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	io->start=(ioaddr_t)(u32)skt->virt_io;
+	io->stop=io->start + IO_MAP_SIZE;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_set_mem_map(struct pcmcia_socket *sock, 
+				     struct pccard_mem_map *io)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+	u32 config;
+	unsigned int speed=io->speed;
+
+	if(io->map >= MAX_WIN) {
+		return -1;
+	}
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+	if(io->flags & MAP_ATTRIB) {
+		config|=M_PCMCIA_CFG_ATTRMEM;
+	}
+	else {
+		config&=~M_PCMCIA_CFG_ATTRMEM;
+	}
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	skt->spd_mem[io->map]=speed;
+
+	io->static_start=skt->phys_mem;
+
+	return 0;
+}
+
+/* the following functions are a gross layer violation. the pcmcia layer hooks 
+ * into the IDE layer to fiddle around with the config register.
+ */
+
+int sb_pcmcia_ack_intr(struct hwif_s *hwif)
+{
+
+	csr_out32(1 << K_GPIO_PC_READY, IOADDR(A_GPIO_CLR_EDGE));
+
+	return 1;
+}
+
+static void sibyte_pcmcia_selectproc(ide_drive_t *drive)
+{
+        u32 config;
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+	config&=~M_PCMCIA_CFG_ATTRMEM;
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+}
+
+static int sibyte_pc_prep_ide(void *iobase)
+{
+	int i;
+	ide_hwif_t *hwif = NULL;
+
+	/* Stake early claim on an ide_hwif */
+	for (i = 0; i < MAX_HWIFS; i++) {
+		if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) {
+			hwif = &ide_hwifs[i]; 
+			break;
+		}
+	}
+	if (hwif == NULL) {
+		 printk("No space for SiByte onboard PCMCIA driver in ide_hwifs[].  Not enabled.\n");
+		 return 1;
+	}
+
+	/*
+	 * Prime the hwif with port values, so when a card is
+	 * detected, the 'io_offset' from the capabilities will lead
+	 * it here
+	 */
+	hwif->hw.io_ports[IDE_DATA_OFFSET]    = iobase + (0);
+	hwif->hw.io_ports[IDE_ERROR_OFFSET]   = iobase + (1);
+	hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = iobase + (2);
+	hwif->hw.io_ports[IDE_SECTOR_OFFSET]  = iobase + (3);
+	hwif->hw.io_ports[IDE_LCYL_OFFSET]    = iobase + (4);
+	hwif->hw.io_ports[IDE_HCYL_OFFSET]    = iobase + (5);
+	hwif->hw.io_ports[IDE_SELECT_OFFSET]  = iobase + (6);
+	hwif->hw.io_ports[IDE_STATUS_OFFSET]  = iobase + (7);
+	hwif->hw.io_ports[IDE_CONTROL_OFFSET] = iobase + (6); /* XXXKW ? */
+	hwif->hw.ack_intr                     = sb_pcmcia_ack_intr;
+	hwif->selectproc                      = sibyte_pcmcia_selectproc;
+	hwif->hold                            = 1;
+	hwif->mmio                            = 2;
+
+	printk("SiByte onboard PCMCIA-IDE configured as device %i\n", i);
+
+	return 0;
+}
+
+/* end of hack */
+static struct pccard_operations sibyte_pcmcia_operations = {
+        .init                   = sibyte_pcmcia_sock_init,
+	.get_status             = sibyte_pcmcia_get_status,
+	.get_socket             = sibyte_pcmcia_get_socket,
+	.set_socket             = sibyte_pcmcia_set_socket,
+	.set_io_map             = sibyte_pcmcia_set_io_map,
+	.set_mem_map            = sibyte_pcmcia_set_mem_map,
+};
+
+static int sibyte_pcmcia_sock_hw_init(struct sibyte_pcmcia_socket *skt)
+{
+
+	u32 status, config;
+	u32 gpio_ctrl;
+
+	status=csr_in32(IOADDR(A_IO_PCMCIA_STATUS));
+
+	config = M_PCMCIA_CFG_CDMASK | M_PCMCIA_CFG_WPMASK | 
+		 M_PCMCIA_CFG_RDYMASK;
+
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	gpio_ctrl=csr_in32(IOADDR(A_GPIO_INT_TYPE));
+	gpio_ctrl&=~M_GPIO_INTR_TYPEX(K_GPIO_PC_READY);
+	gpio_ctrl|=V_GPIO_INTR_TYPEX(K_GPIO_PC_READY, 
+				     K_GPIO_INTR_EDGE);
+
+	csr_out32(gpio_ctrl, IOADDR(A_GPIO_INT_TYPE));
+	csr_out32(1 << K_GPIO_PC_READY, IOADDR(A_GPIO_CLR_EDGE));
+
+	gpio_ctrl=csr_in32(IOADDR(A_GPIO_INPUT_INVERT));
+	gpio_ctrl|=1 << K_GPIO_PC_READY;
+	csr_out32(gpio_ctrl, IOADDR(A_GPIO_INPUT_INVERT));
+
+	if (request_irq(K_INT_PCMCIA, sibyte_pcmcia_interrupt, 0, 
+			"pcmcia", skt))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_socket_probe(struct device *dev, u32 base, u32 size)
+{
+	int ret;
+	struct sibyte_pcmcia_socket *skt=PCMCIA_SOCKET(0);
+
+	skt->socket.ops=&sibyte_pcmcia_operations;
+	skt->socket.resource_ops=&pccard_static_ops;
+	skt->socket.owner=THIS_MODULE;
+	skt->socket.dev.dev=dev;
+
+	skt->irq=K_INT_PC_READY;
+	skt->dev=dev;
+
+	init_timer(&skt->poll_timer);
+	skt->poll_timer.function=sibyte_pcmcia_poll_event;
+	skt->poll_timer.data=(unsigned long)skt;
+	skt->poll_timer.expires=jiffies+SIBYTE_PCMCIA_POLL_PERIOD;
+
+	skt->res_skt.start=base;
+	skt->res_skt.end=base+size;
+	skt->res_skt.name="PCMCIA socket 0";
+	skt->res_skt.flags=IORESOURCE_MEM;
+	ret=request_resource(&iomem_resource, &skt->res_skt);
+	if(ret)
+		goto out_err_1;
+
+	skt->res_io.name="io";
+	skt->res_io.flags=IORESOURCE_MEM | IORESOURCE_BUSY;
+	skt->res_io.start=base;
+	skt->res_io.end=base+IO_MAP_SIZE-1;
+	ret=request_resource(&skt->res_skt, &skt->res_io);
+	if(ret)
+		goto out_err_2;
+	
+	skt->res_mem.name="memory";
+	skt->res_mem.flags=IORESOURCE_MEM;
+	skt->res_mem.start=base+IO_MAP_SIZE;
+	skt->res_mem.end=base+size;
+	ret=request_resource(&skt->res_skt, &skt->res_mem);
+	if(ret)
+		goto out_err_3;
+	
+	skt->virt_io=(void *)(ioremap((phys_t)base, IO_MAP_SIZE) -
+				(u32)mips_io_port_base);
+	skt->phys_mem=base;
+
+	skt->socket.features=SS_CAP_STATIC_MAP|SS_CAP_PCCARD|SS_CAP_PAGE_REGS|
+			     SS_CAP_MEM_ALIGN;
+	skt->socket.irq_mask=0;
+	skt->socket.map_size=size;
+	skt->socket.pci_irq=skt->irq;
+	skt->socket.io_offset=(unsigned long)skt->virt_io;
+
+	skt->status=sibyte_pcmcia_skt_state(skt);
+
+	ret=pcmcia_register_socket(&skt->socket);
+	if(ret)
+		goto out_err_4;
+	
+	ret=sibyte_pcmcia_sock_hw_init(skt);
+	if(ret)
+		goto out_err;
+
+	WARN_ON(skt->socket.sock != 0);
+
+	sibyte_pc_prep_ide(skt->virt_io);
+
+	dev_set_drvdata(dev, skt);
+
+	add_timer(&skt->poll_timer);
+
+	return 0;
+
+out_err:
+	pcmcia_unregister_socket(&skt->socket);
+out_err_4:
+	release_resource(&skt->res_mem);
+out_err_3:
+	release_resource(&skt->res_io);
+out_err_2:
+	release_resource(&skt->res_skt);
+out_err_1:
+	del_timer_sync(&skt->poll_timer);
+	flush_scheduled_work();
+
+	return ret;
+}
+
+
+
+static int sibyte_pcmcia_probe(struct device *dev)
+{
+	u64 cfg;
+	u32 pcmcia_size,pcmcia_base,addr;
+	int ret;
+
+	down(&pcmcia_sockets_lock);
+	cfg=__raw_readq(IOADDR(A_SCD_SYSTEM_CFG));
+	if(!(cfg & M_SYS_PCMCIA_ENABLE)) {
+		printk(KERN_INFO "chip not configured for PCMCIA\n");
+		return -ENODEV;
+	}
+
+	addr=A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, PCMCIA_CS));
+	pcmcia_size=(G_IO_MULT_SIZE(csr_in32(IOADDR(addr))) + 1)<<S_IO_REGSIZE;
+
+	addr=A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, PCMCIA_CS));
+	pcmcia_base=G_IO_START_ADDR(csr_in32(IOADDR(addr))) << S_IO_ADDRBASE;	
+
+	ret=sibyte_pcmcia_socket_probe(dev, pcmcia_base, pcmcia_size);
+
+	up(&pcmcia_sockets_lock);
+
+	return ret;
+}
+
+int sibyte_pcmcia_remove(struct device *dev)
+{
+	struct sibyte_pcmcia_socket *skt=(struct sibyte_pcmcia_socket *)
+					  dev_get_drvdata(dev);
+        down(&pcmcia_sockets_lock);
+
+	dev_set_drvdata(dev, NULL);
+	del_timer_sync(&skt->poll_timer);
+	pcmcia_unregister_socket(&skt->socket);
+	flush_scheduled_work();
+	sibyte_pcmcia_config_skt(skt,&dead_socket);
+	iounmap(skt->virt_io);
+	skt->virt_io = NULL;
+
+	up(&pcmcia_sockets_lock);
+	return 0;
+}
+
+
+static struct device_driver sibyte_pcmcia_driver = {
+	.probe 		= sibyte_pcmcia_probe,
+	.remove 	= sibyte_pcmcia_remove,
+	.name		= "sb1xxx-pcmcia",
+	.bus		= &platform_bus_type,
+};
+
+static struct platform_device sibyte_pcmcia_device = {
+	.name = "sb1xxx-pcmcia",
+	.id = 0,
+};
+
+static int __init sibyte_pcmcia_init(void)
+{
+	int err;
+
+	err=driver_register(&sibyte_pcmcia_driver);
+	if(err)
+		return err;
+
+	platform_device_register(&sibyte_pcmcia_device);
+
+	return 0;
+}
+
+static void __exit sibyte_pcmcia_exit(void)
+{
+	driver_unregister(&sibyte_pcmcia_driver);
+	platform_device_unregister(&sibyte_pcmcia_device);
+}
+
+
+EXPORT_SYMBOL(sb_pcmcia_ack_intr);
+
+module_init(sibyte_pcmcia_init);
+module_exit(sibyte_pcmcia_exit);
+
diff -urN -x asm -x scripts -x config linux/include/asm-mips/ide.h linux-my/include/asm-mips/ide.h
--- linux/include/asm-mips/ide.h	2004-11-24 19:35:14.000000000 +0100
+++ linux-my/include/asm-mips/ide.h	2005-09-22 17:47:08.000000000 +0200
@@ -10,4 +10,9 @@
 
 #include <ide.h>
 
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+#define IDE_ARCH_ACK_INTR
+#define ide_ack_intr(hwif)      ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
+#endif
+
 #endif /* __ASM_IDE_H */