/* #define ATR_CSUM */
#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 { \
#define T_100MSEC msecs_to_jiffies(100)
#define T_500MSEC msecs_to_jiffies(500)
-static void cm4000_release(struct pcmcia_device *link);
+static void cm4000_release(dev_link_t *link);
static int major; /* major number we get from the kernel */
#define REG_STOPBITS(x) (x + 7)
struct cm4000_dev {
- struct pcmcia_device *p_dev;
+ dev_link_t link; /* pcmcia link */
dev_node_t node; /* OS node (major,minor) */
unsigned char atr[MAX_ATR];
#define ZERO_DEV(dev) \
memset(&dev->atr_csum,0, \
sizeof(struct cm4000_dev) - \
- /*link*/ sizeof(struct pcmcia_device *) - \
+ /*link*/ sizeof(dev_link_t) - \
/*node*/ sizeof(dev_node_t) - \
/*atr*/ MAX_ATR*sizeof(char) - \
/*rbuf*/ 512*sizeof(char) - \
/*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t))
-static struct pcmcia_device *dev_table[CM4000_MAX_DEV];
+static dev_link_t *dev_table[CM4000_MAX_DEV];
static struct class *cmm_class;
/* This table doesn't use spaces after the comma between fields and thus
static void set_cardparameter(struct cm4000_dev *dev)
{
int i;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ ioaddr_t iobase = dev->link.io.BasePort1;
u_int8_t stopbits = 0x02; /* ISO default */
DEBUGP(3, dev, "-> set_cardparameter\n");
unsigned short num_bytes_read;
unsigned char pts_reply[4];
ssize_t rc;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ ioaddr_t iobase = dev->link.io.BasePort1;
rc = 0;
static void monitor_card(unsigned long p)
{
struct cm4000_dev *dev = (struct cm4000_dev *) p;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ ioaddr_t iobase = dev->link.io.BasePort1;
unsigned short s;
struct ptsreq ptsreq;
int i, atrc;
loff_t *ppos)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ ioaddr_t iobase = dev->link.io.BasePort1;
ssize_t rc;
int i, j, k;
if (count == 0) /* according to manpage */
return 0;
- if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
+ if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
size_t count, loff_t *ppos)
{
struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
+ ioaddr_t iobase = dev->link.io.BasePort1;
unsigned short s;
unsigned char tmp;
unsigned char infolen;
sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0;
- if (!pcmcia_dev_present(dev->p_dev) || /* device removed */
+ if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */
test_bit(IS_CMM_ABSENT, &dev->flags))
return -ENODEV;
unsigned long arg)
{
struct cm4000_dev *dev = filp->private_data;
- ioaddr_t iobase = dev->p_dev->io.BasePort1;
- struct pcmcia_device *link;
+ ioaddr_t iobase = dev->link.io.BasePort1;
+ dev_link_t *link;
int size;
int rc;
void __user *argp = (void __user *)arg;
iminor(inode), ioctl_names[_IOC_NR(cmd)]);
link = dev_table[iminor(inode)];
- if (!pcmcia_dev_present(link)) {
+ if (!(DEV_OK(link))) {
DEBUGP(4, dev, "DEV_OK false\n");
return -ENODEV;
}
static int cmm_open(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- struct pcmcia_device *link;
+ dev_link_t *link;
int rc, minor = iminor(inode);
if (minor >= CM4000_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 cmm_close(struct inode *inode, struct file *filp)
{
struct cm4000_dev *dev;
- struct pcmcia_device *link;
+ dev_link_t *link;
int minor = iminor(inode);
if (minor >= CM4000_MAX_DEV)
return 0;
}
-static void cmm_cm4000_release(struct pcmcia_device * link)
+static void cmm_cm4000_release(dev_link_t * link)
{
struct cm4000_dev *dev = link->priv;
/*==== Interface to PCMCIA Layer =======================================*/
-static int cm4000_config(struct pcmcia_device * link, int devno)
+static void cm4000_config(dev_link_t * link, int devno)
{
+ client_handle_t handle = link->handle;
struct cm4000_dev *dev;
tuple_t tuple;
cisparse_t parse;
+ config_info_t conf;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
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)) != CS_SUCCESS) {
+ 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);
- rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
+ for (rc = pcmcia_get_first_tuple(handle, &tuple);
+ rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) {
- rc = pcmcia_get_tuple_data(link, &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.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(link, &link->io);
+ rc = pcmcia_request_io(handle, &link->io);
if (rc == CS_SUCCESS)
break; /* we are done */
}
link->conf.IntType = 00000002;
if ((fail_rc =
- pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
+ pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) {
fail_fn = RequestConfiguration;
goto cs_release;
}
dev->node.major = major;
dev->node.minor = devno;
dev->node.next = NULL;
- link->dev_node = &dev->node;
+ link->dev = &dev->node;
+ link->state &= ~DEV_CONFIG_PENDING;
- return 0;
+ return;
cs_failed:
- cs_error(link, fail_fn, fail_rc);
+ cs_error(handle, fail_fn, fail_rc);
cs_release:
cm4000_release(link);
- return -ENODEV;
+
+ link->state &= ~DEV_CONFIG_PENDING;
}
-static int cm4000_suspend(struct pcmcia_device *link)
+static int cm4000_suspend(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
stop_monitor(dev);
return 0;
}
-static int cm4000_resume(struct pcmcia_device *link)
+static int cm4000_resume(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
dev = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+
if (link->open)
start_monitor(dev);
return 0;
}
-static void cm4000_release(struct pcmcia_device *link)
+static void cm4000_release(dev_link_t *link)
{
cmm_cm4000_release(link->priv); /* delay release until device closed */
- pcmcia_disable_device(link);
+ pcmcia_release_configuration(link->handle);
+ pcmcia_release_io(link->handle, &link->io);
}
-static int cm4000_probe(struct pcmcia_device *link)
+static int cm4000_attach(struct pcmcia_device *p_dev)
{
struct cm4000_dev *dev;
- int i, ret;
+ dev_link_t *link;
+ int i;
for (i = 0; i < CM4000_MAX_DEV; i++)
if (dev_table[i] == NULL)
if (dev == NULL)
return -ENOMEM;
- dev->p_dev = link;
+ link = &dev->link;
link->priv = dev;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_waitqueue_head(&dev->atrq);
init_waitqueue_head(&dev->readq);
- ret = cm4000_config(link, i);
- if (ret)
- return ret;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ cm4000_config(link, i);
class_device_create(cmm_class, NULL, MKDEV(major, i), NULL,
"cmm%d", i);
return 0;
}
-static void cm4000_detach(struct pcmcia_device *link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev = link->priv;
int devno;
if (devno == CM4000_MAX_DEV)
return;
+ link->state &= ~DEV_PRESENT;
stop_monitor(dev);
- cm4000_release(link);
+ if (link->state & DEV_CONFIG)
+ cm4000_release(link);
dev_table[devno] = NULL;
kfree(dev);
.drv = {
.name = "cm4000_cs",
},
- .probe = cm4000_probe,
+ .probe = cm4000_attach,
.remove = cm4000_detach,
.suspend = cm4000_suspend,
.resume = cm4000_resume,