diff -ruN linux/drivers/pcmcia.orig/Kconfig linux/drivers/pcmcia/Kconfig --- linux/drivers/pcmcia.orig/Kconfig 2004-01-09 15:59:48.000000000 +0900 +++ linux/drivers/pcmcia/Kconfig 2004-01-13 21:28:09.000000000 +0900 @@ -50,6 +50,13 @@ depends on YENTA default y if YENTA +config PD6729 + tristate "Cirrus PD6729 compatible bridge support" + depends on PCMCIA && PCI + help + This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge device, + found in some older laptops and PCMCIA card readers. + config I82092 tristate "i82092 compatible bridge support" depends on PCMCIA && PCI diff -ruN linux/drivers/pcmcia.orig/Makefile linux/drivers/pcmcia/Makefile --- linux/drivers/pcmcia.orig/Makefile 2004-01-09 15:59:55.000000000 +0900 +++ linux/drivers/pcmcia/Makefile 2004-01-13 21:28:09.000000000 +0900 @@ -5,6 +5,7 @@ obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o obj-$(CONFIG_YENTA) += yenta_socket.o +obj-$(CONFIG_PD6729) += pd6729.o obj-$(CONFIG_I82365) += i82365.o obj-$(CONFIG_I82092) += i82092.o obj-$(CONFIG_TCIC) += tcic.o diff -ruN linux/drivers/pcmcia.orig/pd6729.c linux/drivers/pcmcia/pd6729.c --- linux/drivers/pcmcia.orig/pd6729.c 1970-01-01 09:00:00.000000000 +0900 +++ linux/drivers/pcmcia/pd6729.c 2004-02-01 11:40:35.893397648 +0900 @@ -0,0 +1,759 @@ +/* + * Driver for the Cirrus PD6729 PCI-PCMCIA bridge. + * + * Based on the i82092.c driver. + * + * This software may be used and distributed according to the terms of + * the GNU General Public License, incorporated herein by reference. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "pd6729.h" +#include "i82365.h" +#include "cirrus.h" + +MODULE_LICENSE("GPL"); + +/* PCI core routines */ +static struct pci_device_id pd6729_pci_ids[] = { + { + .vendor = PCI_VENDOR_ID_CIRRUS, + .device = PCI_DEVICE_ID_CIRRUS_6729, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + {} +}; +MODULE_DEVICE_TABLE(pci, pd6729_pci_ids); + +static int pd6729_socket_suspend (struct pci_dev *dev, u32 state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int pd6729_socket_resume (struct pci_dev *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} + +static struct pci_driver pd6729_pci_drv = { + .name = "pd6729", + .id_table = pd6729_pci_ids, + .probe = pd6729_pci_probe, + .remove = __devexit_p(pd6729_pci_remove), + .suspend = pd6729_socket_suspend, + .resume = pd6729_socket_resume, +}; + + +/* the pccard structure and its functions */ +static struct pccard_operations pd6729_operations = { + .init = pd6729_init, + .suspend = pd6729_suspend, + .get_status = pd6729_get_status, + .get_socket = pd6729_get_socket, + .set_socket = pd6729_set_socket, + .set_io_map = pd6729_set_io_map, + .set_mem_map = pd6729_set_mem_map, +}; + +/* The card can do upto 4 sockets, allocate a structure for each of them */ + +struct socket_info { + int number; + int card_state; /* 0 = no socket, + 1 = empty socket, + 2 = card but not initialized, + 3 = operational card */ + int io_base; /* base io address of the socket */ + + struct pcmcia_socket socket; + struct pci_dev *dev; /* The PCI device for the socket */ +}; + +#define MAX_SOCKETS 4 +static struct socket_info sockets[MAX_SOCKETS]; +static int socket_count; /* shortcut */ + +static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int i, ret; + char configbyte; + + if ((ret = pci_enable_device(dev))) + return ret; + + socket_count = 2; + printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge.\n"); + printk(KERN_INFO "pd6729: configured as a %d socket device.\n", socket_count); + /* Since we have no memory BARs some firmware we may not + have had PCI_COMMAND_MEM enabled, yet the device needs + it. */ + pci_read_config_byte(dev, PCI_COMMAND, &configbyte); + if (!(configbyte & PCI_COMMAND_MEMORY)) { + printk(KERN_DEBUG "pd6729: Enabling PCI_COMMAND_MEMORY.\n"); + configbyte |= PCI_COMMAND_MEMORY; + pci_write_config_byte(dev, PCI_COMMAND, configbyte); + } + + if (pci_request_regions(dev, "pd6729")) { + ret = -EBUSY; + goto err_out_disable; + } + + for (i = 0;iirq; + sockets[i].socket.owner = THIS_MODULE; + + sockets[i].number = i; + + if (card_present(i)) { + sockets[i].card_state = 3; + dprintk(KERN_DEBUG "pd6729: slot %i is occupied\n",i); + } else { + dprintk(KERN_DEBUG "pd6729: slot %i is vacant\n",i); + } + } + + /* Register the interrupt handler */ + dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq); + if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, "pd6729", pd6729_interrupt))) { + printk(KERN_ERR "pd6729: Failed to register IRQ %d, aborting\n", dev->irq); + goto err_out_free_res; + } + + pci_set_drvdata(dev, &sockets[i].socket); + + for (i = 0; idev; + sockets[i].socket.ops = &pd6729_operations; + ret = pcmcia_register_socket(&sockets[i].socket); + if (ret) { + goto err_out_free_sockets; + } + } + + return 0; + +err_out_free_sockets: + if (i) { + for (i--;i>=0;i--) { + pcmcia_unregister_socket(&sockets[i].socket); + } + } + free_irq(dev->irq, pd6729_interrupt); +err_out_free_res: + pci_release_regions(dev); +err_out_disable: + pci_disable_device(dev); + return ret; +} + +static void __devexit pd6729_pci_remove(struct pci_dev *dev) +{ + int i; + + for (i = socket_count-1; i >=0 ; i--) + pcmcia_unregister_socket(&sockets[i].socket); + + free_irq(dev->irq, pd6729_interrupt); + pci_release_regions(dev); +} + +static spinlock_t port_lock = SPIN_LOCK_UNLOCKED; + +/* basic value read/write functions */ + +static unsigned char indirect_read(int socket, unsigned short reg) +{ + unsigned short int port; + unsigned char val; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg += socket * 0x40; + port = sockets[socket].io_base; + outb(reg,port); + val = inb(port+1); + spin_unlock_irqrestore(&port_lock,flags); + return val; +} + +static unsigned short indirect_read16(int socket, unsigned short reg) +{ + unsigned short int port; + unsigned short tmp; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg = reg + socket * 0x40; + port = sockets[socket].io_base; + outb(reg,port); + tmp = inb(port+1); + reg++; + outb(reg,port); + tmp = tmp | (inb(port+1)<<8); + spin_unlock_irqrestore(&port_lock,flags); + return tmp; +} + +static void indirect_write(int socket, unsigned short reg, unsigned char value) +{ + unsigned short int port; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg = reg + socket * 0x40; + port = sockets[socket].io_base; + outb(reg,port); + outb(value,port+1); + spin_unlock_irqrestore(&port_lock,flags); +} + +static void indirect_setbit(int socket, unsigned short reg, unsigned char mask) +{ + unsigned short int port; + unsigned char val; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg = reg + socket * 0x40; + port = sockets[socket].io_base; + outb(reg,port); + val = inb(port+1); + val |= mask; + outb(reg,port); + outb(val,port+1); + spin_unlock_irqrestore(&port_lock,flags); +} + +static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask) +{ + unsigned short int port; + unsigned char val; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg = reg + socket * 0x40; + port = sockets[socket].io_base; + outb(reg,port); + val = inb(port+1); + val &= ~mask; + outb(reg,port); + outb(val,port+1); + spin_unlock_irqrestore(&port_lock,flags); +} + +static void indirect_write16(int socket, unsigned short reg, unsigned short value) +{ + unsigned short int port; + unsigned char val; + unsigned long flags; + spin_lock_irqsave(&port_lock,flags); + reg = reg + socket * 0x40; + port = sockets[socket].io_base; + + outb(reg,port); + val = value & 255; + outb(val,port+1); + + reg++; + + outb(reg,port); + val = value>>8; + outb(val,port+1); + spin_unlock_irqrestore(&port_lock,flags); +} + +/* simple helper functions */ +/* External clock time, in nanoseconds. 120 ns = 8.33 MHz */ +static int cycle_time = 120; + +static int to_cycles(int ns) +{ + if (cycle_time!=0) + return ns/cycle_time; + else + return 0; +} + +/* Interrupt handler functionality */ + +static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + int i; + int loopcount = 0; + int handled = 0; + + unsigned int events, active=0; + + while (1) { + loopcount++; + if (loopcount>20) { + printk(KERN_ERR "pd6729: infinite eventloop in interrupt \n"); + break; + } + + active = 0; + + for (i=0;i= MAX_SOCKETS)) + return 0; + if (sockets[socketno].io_base == 0) + return 0; + + val = indirect_read(socketno, 1); /* Interface status register */ + if ((val&12)==12) { + dprintk("card_present 1"); + return 1; + } + + dprintk("card_present 0"); + return 0; +} + +static void set_bridge_state(int sock) +{ + indirect_write(sock, I365_GBLCTL,0x00); + indirect_write(sock, I365_GENCTL,0x00); + + indirect_setbit(sock, I365_INTCTL,0x08); +} + +static int pd6729_init(struct pcmcia_socket *sock) +{ + int i; + pccard_io_map io = { 0, 0, 0, 0, 1 }; + pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; + + mem.sys_stop = 0x0fff; + pd6729_set_socket(sock, &dead_socket); + for (i = 0; i < 2; i++) { + io.map = i; + pd6729_set_io_map(sock, &io); + } + for (i = 0; i < 5; i++) { + mem.map = i; + pd6729_set_mem_map(sock, &mem); + } + + return 0; +} + +static int pd6729_suspend(struct pcmcia_socket *sock) +{ + int retval; + retval = pd6729_set_socket(sock, &dead_socket); + return retval; +} + +static int pd6729_get_status(struct pcmcia_socket *socket, u_int *value) +{ + unsigned int sock = container_of(socket, struct socket_info, socket)->number; + unsigned int status; + unsigned int data, t; + + status = indirect_read(sock,I365_STATUS); /* Interface Status Register */ + *value = 0; + + if ((status & I365_CS_DETECT) == I365_CS_DETECT) { + *value |= SS_DETECT; + } + + /* IO cards have a different meaning of bits 0,1 */ + /* Also notice the inverse-logic on the bits */ + if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) { + /* IO card */ + if (!(status & I365_CS_STSCHG)) + *value |= SS_STSCHG; + } else { /* non I/O card */ + if (!(status & I365_CS_BVD1)) + *value |= SS_BATDEAD; + if (!(status & I365_CS_BVD2)) + *value |= SS_BATWARN; + + } + + if (status & I365_CS_WRPROT) + (*value) |= SS_WRPROT; /* card is write protected */ + + if (status & I365_CS_READY) + (*value) |= SS_READY; /* card is not busy */ + + if (status & I365_CS_POWERON) + (*value) |= SS_POWERON; /* power is applied to the card */ + + t = (sock) ? sock : sock+1; + indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA); + data = indirect_read16(t, PD67_EXT_DATA); + *value |= (data & PD67_EXD_VS1(sock)) ? 0 : SS_3VCARD; /* 3.3V card */ + + return 0; +} + + +static int pd6729_get_socket(struct pcmcia_socket *socket, socket_state_t *state) +{ + unsigned int sock = container_of(socket, struct socket_info, socket)->number; + unsigned char reg,vcc,vpp; + + state->flags = 0; + state->Vcc = 0; + state->Vpp = 0; + state->io_irq = 0; + state->csc_mask = 0; + + /* First the power status of the socket */ + reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */ + + if (reg & I365_PWR_AUTO) + state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */ + + if (reg & I365_PWR_OUT) + state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */ + + vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK; + + if (reg & I365_VCC_5V) { + state->Vcc = (indirect_read(sock, PD67_MISC_CTL_1) & + PD67_MC1_VCC_3V) ? 33 : 50; + + if (vpp == I365_VPP1_5V) { + if (state->Vcc == 50) state->Vpp = 50; + else state->Vpp = 33; + } + if (vpp == I365_VPP1_12V) + state->Vpp = 120; + + } + + /* Now the IO card, RESET flags and IO interrupt */ + + reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */ + + if ((reg & I365_PC_RESET)==0) + state->flags |= SS_RESET; + if (reg & I365_PC_IOCARD) + state->flags |= SS_IOCARD; /* This is an IO card */ + + /* Set the IRQ number */ + if (sockets[sock].dev!=NULL) + state->io_irq = sockets[sock].dev->irq; + + /* Card status change */ + reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */ + + if (reg & I365_CSC_DETECT) + state->csc_mask |= SS_DETECT; /* Card detect is enabled */ + + if (state->flags & SS_IOCARD) {/* IO Cards behave different */ + if (reg & I365_CSC_STSCHG) + state->csc_mask |= SS_STSCHG; + } else { + if (reg & I365_CSC_BVD1) + state->csc_mask |= SS_BATDEAD; + if (reg & I365_CSC_BVD2) + state->csc_mask |= SS_BATWARN; + if (reg & I365_CSC_READY) + state->csc_mask |= SS_READY; + } + + return 0; +} + +static int pd6729_set_socket(struct pcmcia_socket *socket, socket_state_t *state) +{ + unsigned int sock = container_of(socket, struct socket_info, socket)->number; + unsigned char reg; + + /* First, set the global controller options */ + + set_bridge_state(sock); + + /* Values for the IGENC register */ + + reg = 0; + if (!(state->flags & SS_RESET)) /* The reset bit has "inverse" logic */ + reg = reg | I365_PC_RESET; + if (state->flags & SS_IOCARD) + reg = reg | I365_PC_IOCARD; + + indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */ + + /* Power registers */ + + reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ + + if (state->flags & SS_PWR_AUTO) { + dprintk("Auto power\n"); + reg |= I365_PWR_AUTO; /* automatic power mngmnt */ + } + if (state->flags & SS_OUTPUT_ENA) { + dprintk("Power Enabled \n"); + reg |= I365_PWR_OUT; /* enable power */ + } + + switch (state->Vcc) { + case 0: + break; + case 33: + dprintk("setting voltage to Vcc to 3.3V on socket %i\n",sock); + reg |= I365_VCC_5V; + indirect_setbit(sock,PD67_MISC_CTL_1,PD67_MC1_VCC_3V); + break; + case 50: + dprintk("setting voltage to Vcc to 5V on socket %i\n",sock); + reg |= I365_VCC_5V; + indirect_resetbit(sock,PD67_MISC_CTL_1,PD67_MC1_VCC_3V); + break; + default: + dprintk("pd6729: pd6729_set_socket called with invalid VCC power value: %i ", state->Vcc); + return -EINVAL; + } + + switch (state->Vpp) { + case 0: + dprintk("not setting Vpp on socket %i\n",sock); + break; + case 33: + case 50: + dprintk("setting Vpp to Vcc for socket %i\n",sock); + reg |= I365_VPP1_5V; + break; + case 120: + dprintk("setting Vpp to 12.0\n"); + reg |= I365_VPP1_12V; + break; + default: + dprintk("pd6729: pd6729_set_socket called with invalid VPP power value: %i ", state->Vpp); + return -EINVAL; + } + + if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */ + indirect_write(sock,I365_POWER,reg); + + /* Now, specifiy that all interrupts are to be done as PCI interrupts */ + indirect_write(sock, PD67_EXT_INDEX, PD67_EXT_CTL_1); + indirect_write(sock, PD67_EXT_DATA, PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ); + + /* Enable specific interrupt events */ + + reg = 0x00; + if (state->csc_mask & SS_DETECT) { + reg |= I365_CSC_DETECT; + } + if (state->flags & SS_IOCARD) { + if (state->csc_mask & SS_STSCHG) + reg |= I365_CSC_STSCHG; + } else { + if (state->csc_mask & SS_BATDEAD) + reg |= I365_CSC_BVD1; + if (state->csc_mask & SS_BATWARN) + reg |= I365_CSC_BVD2; + if (state->csc_mask & SS_READY) + reg |= I365_CSC_READY; + } + reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */ + indirect_write(sock,I365_CSCINT,reg); + + reg = indirect_read(sock,I365_INTCTL); + reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */ + indirect_write(sock,I365_INTCTL,reg); + + /* now clear the (probably bogus) pending stuff by doing a dummy read*/ + (void)indirect_read(sock,I365_CSC); + + return 0; +} + +static int pd6729_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io) +{ + unsigned int sock = container_of(socket, struct socket_info, socket)->number; + unsigned char map, ioctl; + + map = io->map; + + /* Check error conditions */ + if (map > 1) { + dprintk("pd6729_set_io_map with invalid map"); + return -EINVAL; + } + if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){ + dprintk("pd6729_set_io_map with invalid io"); + return -EINVAL; + } + + /* Turn off the window before changing anything */ + if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map)) + indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map)); + +/* printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop); */ + + /* write the new values */ + indirect_write16(sock,I365_IO(map)+I365_W_START,io->start); + indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop); + + ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map); + + if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map); + if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map); + if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map); + + indirect_write(sock,I365_IOCTL,ioctl); + + /* Turn the window back on if needed */ + if (io->flags & MAP_ACTIVE) + indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map)); + + return 0; +} + +static int pd6729_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) +{ + unsigned int sock = container_of(socket, struct socket_info, socket)->number; + unsigned short base, i; + unsigned char map; + + map = mem->map; + if (map > 4) { + printk("pd6729_set_mem_map: invalid map"); + return -EINVAL; + } + + if ( (mem->sys_start > mem->sys_stop) || (mem->speed > 1000) ) { + printk("pd6729_set_mem_map: invalid address / speed"); + printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start); + return -EINVAL; + } + + /* Turn off the window before changing anything */ + if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) + indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); + +/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE); */ + + /* write the start address */ + base = I365_MEM(map); + i = (mem->sys_start >> 12) & 0x0fff; + if (mem->flags & MAP_16BIT) + i |= I365_MEM_16BIT; + if (mem->flags & MAP_0WS) + i |= I365_MEM_0WS; + indirect_write16(sock,base+I365_W_START,i); + + /* write the stop address */ + + i= (mem->sys_stop >> 12) & 0x0fff; + switch (to_cycles(mem->speed)) { + case 0: + break; + case 1: + i |= I365_MEM_WS0; + break; + case 2: + i |= I365_MEM_WS1; + break; + default: + i |= I365_MEM_WS1 | I365_MEM_WS0; + break; + } + + indirect_write16(sock,base+I365_W_STOP,i); + + /* Take care of high byte */ + indirect_write(sock, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); + indirect_write(sock, PD67_EXT_DATA, mem->sys_start >> 24); + + /* card start */ + + i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + if (mem->flags & MAP_WRPROT) + i |= I365_MEM_WRPROT; + if (mem->flags & MAP_ATTRIB) { +/* printk("requesting attribute memory for socket %i\n",sock);*/ + i |= I365_MEM_REG; + } else { +/* printk("requesting normal memory for socket %i\n",sock);*/ + } + indirect_write16(sock,base+I365_W_OFF,i); + + /* Enable the window if necessary */ + if (mem->flags & MAP_ACTIVE) + indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); + + return 0; +} + +static int pd6729_module_init(void) +{ + return pci_module_init (&pd6729_pci_drv); +} + +static void pd6729_module_exit(void) +{ + pci_unregister_driver(&pd6729_pci_drv); +} + +module_init(pd6729_module_init); +module_exit(pd6729_module_exit); + diff -ruN linux/drivers/pcmcia.orig/pd6729.h linux/drivers/pcmcia/pd6729.h --- linux/drivers/pcmcia.orig/pd6729.h 1970-01-01 09:00:00.000000000 +0900 +++ linux/drivers/pcmcia/pd6729.h 2004-01-13 21:28:09.000000000 +0900 @@ -0,0 +1,42 @@ +#ifndef _INCLUDE_GUARD_PD6729_H_ +#define _INCLUDE_GUARD_PD6729_H_ + +#include + + +/* Debuging defines */ +#ifdef NOTRACE +#define enter(x) printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__) +#define leave(x) printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__) +#define dprintk(fmt, args...) printk(fmt , ## args) +#else +#define enter(x) do {} while (0) +#define leave(x) do {} while (0) +#define dprintk(fmt, args...) do {} while (0) +#endif + + +/* Flags for I365_GENCTL */ +#define I365_DF_VS1 0x40 /* DF-step Voltage Sense */ +#define I365_DF_VS2 0x80 + +/* Fields in PD67_EXTERN_DATA */ +#define PD67_EXD_VS1(s) (0x01 << ((s)<<1)) +#define PD67_EXD_VS2(s) (0x02 << ((s)<<1)) + +/* prototypes */ + +static int pd6729_pci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void pd6729_pci_remove(struct pci_dev *dev); +static int card_present(int socketno); +static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs); +static int pd6729_get_status(struct pcmcia_socket *socket, u_int *value); +static int pd6729_get_socket(struct pcmcia_socket *socket, socket_state_t *state); +static int pd6729_set_socket(struct pcmcia_socket *socket, socket_state_t *state); +static int pd6729_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io); +static int pd6729_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); +static int pd6729_init(struct pcmcia_socket *socket); +static int pd6729_suspend(struct pcmcia_socket *socket); + +#endif +