#ifdef PCMCIA_DEBUG
-#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle))
+#define reader_to_dev(x) (&handle_to_dev(x->link.handle))
static int pc_debug = PCMCIA_DEBUG;
module_param(pc_debug, int, 0600);
#define DEBUGP(n, rdr, x, args...) do { \
/* how often to poll for fifo status change */
#define POLL_PERIOD msecs_to_jiffies(10)
-static void reader_release(struct pcmcia_device *link);
+static void reader_release(dev_link_t *link);
static int major;
static struct class *cmx_class;
#define BS_WRITABLE 0x02
struct reader_dev {
- struct pcmcia_device *p_dev;
+ dev_link_t link;
dev_node_t node;
wait_queue_head_t devq;
wait_queue_head_t poll_wait;
struct timer_list poll_timer;
};
-static struct pcmcia_device *dev_table[CM_MAX_DEV];
+static dev_link_t *dev_table[CM_MAX_DEV];
#ifndef PCMCIA_DEBUG
#define xoutb outb
static void cm4040_do_poll(unsigned long dummy)
{
struct reader_dev *dev = (struct reader_dev *) dummy;
- unsigned int obs = xinb(dev->p_dev->io.BasePort1
+ unsigned int obs = xinb(dev->link.io.BasePort1
+ REG_OFFSET_BUFFER_STATUS);
if ((obs & BSR_BULK_IN_FULL)) {
static int wait_for_bulk_out_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->p_dev->io.BasePort1;
+ int iobase = dev->link.io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
/* Write to Sync Control Register */
static int write_sync_reg(unsigned char val, struct reader_dev *dev)
{
- int iobase = dev->p_dev->io.BasePort1;
+ int iobase = dev->link.io.BasePort1;
int rc;
rc = wait_for_bulk_out_ready(dev);
static int wait_for_bulk_in_ready(struct reader_dev *dev)
{
int i, rc;
- int iobase = dev->p_dev->io.BasePort1;
+ int iobase = dev->link.io.BasePort1;
for (i = 0; i < POLL_LOOP_COUNT; i++) {
if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->p_dev->io.BasePort1;
+ int iobase = dev->link.io.BasePort1;
size_t bytes_to_read;
unsigned long i;
size_t min_bytes_to_read;
return -EAGAIN;
}
- if (!pcmcia_dev_present(dev->p_dev))
+ if ((dev->link.state & DEV_PRESENT)==0)
return -ENODEV;
for (i = 0; i < 5; i++) {
size_t count, loff_t *ppos)
{
struct reader_dev *dev = filp->private_data;
- int iobase = dev->p_dev->io.BasePort1;
+ int iobase = dev->link.io.BasePort1;
ssize_t rc;
int i;
unsigned int bytes_to_write;
return -EAGAIN;
}
- if (!pcmcia_dev_present(dev->p_dev))
+ if ((dev->link.state & DEV_PRESENT) == 0)
return -ENODEV;
bytes_to_write = count;
static int cm4040_open(struct inode *inode, struct file *filp)
{
struct reader_dev *dev;
- struct pcmcia_device *link;
+ dev_link_t *link;
int minor = iminor(inode);
if (minor >= CM_MAX_DEV)
return -ENODEV;
link = dev_table[minor];
- if (link == NULL || !pcmcia_dev_present(link))
+ if (link == NULL || !(DEV_OK(link)))
return -ENODEV;
if (link->open)
static int cm4040_close(struct inode *inode, struct file *filp)
{
struct reader_dev *dev = filp->private_data;
- struct pcmcia_device *link;
+ dev_link_t *link;
int minor = iminor(inode);
DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode),
return 0;
}
-static void cm4040_reader_release(struct pcmcia_device *link)
+static void cm4040_reader_release(dev_link_t *link)
{
struct reader_dev *dev = link->priv;
return;
}
-static int reader_config(struct pcmcia_device *link, int devno)
+static void reader_config(dev_link_t *link, int devno)
{
+ client_handle_t handle;
struct reader_dev *dev;
tuple_t tuple;
cisparse_t parse;
+ config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
+ handle = link->handle;
+
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
- if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
- if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
+ if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
- if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
+ if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse))
!= CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
+ if ((fail_rc = pcmcia_get_configuration_info(handle, &conf))
+ != CS_SUCCESS) {
+ fail_fn = GetConfigurationInfo;
+ goto cs_failed;
+ }
+ link->state |= DEV_CONFIG;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
+ link->conf.Vcc = conf.Vcc;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (rc = pcmcia_get_first_tuple(link, &tuple);
+ for (rc = pcmcia_get_first_tuple(handle, &tuple);
rc == CS_SUCCESS;
- rc = pcmcia_get_next_tuple(link, &tuple)) {
- rc = pcmcia_get_tuple_data(link, &tuple);
+ rc = pcmcia_get_next_tuple(handle, &tuple)) {
+ rc = pcmcia_get_tuple_data(handle, &tuple);
if (rc != CS_SUCCESS)
continue;
- rc = pcmcia_parse_tuple(link, &tuple, &parse);
+ rc = pcmcia_parse_tuple(handle, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(link, &link->io);
+ rc = pcmcia_request_io(handle, &link->io);
- dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
+ dev_printk(KERN_INFO, &handle_to_dev(handle), "foo");
if (rc == CS_SUCCESS)
break;
else
- dev_printk(KERN_INFO, &handle_to_dev(link),
+ dev_printk(KERN_INFO, &handle_to_dev(handle),
"pcmcia_request_io failed 0x%x\n", rc);
}
if (rc != CS_SUCCESS)
link->conf.IntType = 00000002;
- if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
+ if ((fail_rc = pcmcia_request_configuration(handle,&link->conf))
!=CS_SUCCESS) {
fail_fn = RequestConfiguration;
- dev_printk(KERN_INFO, &handle_to_dev(link),
+ dev_printk(KERN_INFO, &handle_to_dev(handle),
"pcmcia_request_configuration failed 0x%x\n",
fail_rc);
goto cs_release;
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
dev->node.major = major;
dev->node.minor = devno;
- dev->node.next = &dev->node;
+ dev->node.next = NULL;
+ link->dev = &dev->node;
+ link->state &= ~DEV_CONFIG_PENDING;
DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
DEBUGP(2, dev, "<- reader_config (succ)\n");
- return 0;
+ return;
cs_failed:
- cs_error(link, fail_fn, fail_rc);
+ cs_error(handle, fail_fn, fail_rc);
cs_release:
reader_release(link);
- return -ENODEV;
+ link->state &= ~DEV_CONFIG_PENDING;
+}
+
+static int reader_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
}
-static void reader_release(struct pcmcia_device *link)
+static int reader_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ return 0;
+}
+
+static void reader_release(dev_link_t *link)
{
cm4040_reader_release(link->priv);
- pcmcia_disable_device(link);
+ pcmcia_release_configuration(link->handle);
+ pcmcia_release_io(link->handle, &link->io);
}
-static int reader_probe(struct pcmcia_device *link)
+static int reader_attach(struct pcmcia_device *p_dev)
{
struct reader_dev *dev;
- int i, ret;
+ dev_link_t *link;
+ int i;
for (i = 0; i < CM_MAX_DEV; i++) {
if (dev_table[i] == NULL)
dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
dev->buffer_status = 0;
+ link = &dev->link;
link->priv = dev;
- dev->p_dev = link;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_timer(&dev->poll_timer);
dev->poll_timer.function = &cm4040_do_poll;
- ret = reader_config(link, i);
- if (ret)
- return ret;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ reader_config(link, i);
class_device_create(cmx_class, NULL, MKDEV(major, i), NULL,
"cmx%d", i);
return 0;
}
-static void reader_detach(struct pcmcia_device *link)
+static void reader_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev = link->priv;
int devno;
if (devno == CM_MAX_DEV)
return;
- reader_release(link);
+ link->state &= ~DEV_PRESENT;
+
+ if (link->state & DEV_CONFIG)
+ reader_release(link);
dev_table[devno] = NULL;
kfree(dev);
.drv = {
.name = "cm4040_cs",
},
- .probe = reader_probe,
+ .probe = reader_attach,
.remove = reader_detach,
+ .suspend = reader_suspend,
+ .resume = reader_resume,
.id_table = cm4040_ids,
};