#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
-#include <linux/usb_sl811.h>
+#include <linux/usb/sl811.h>
MODULE_AUTHOR("Botond Botyanszki");
MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6");
dev_node_t node;
} local_info_t;
-static void sl811_cs_release(dev_link_t * link);
+static void sl811_cs_release(struct pcmcia_device * link);
/*====================================================================*/
.num_resources = ARRAY_SIZE(resources),
};
-static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
+static int sl811_hc_init(struct device *parent, resource_size_t base_addr,
+ int irq)
{
if (platform_dev.dev.parent)
return -EBUSY;
/*====================================================================*/
-static void sl811_cs_detach(struct pcmcia_device *p_dev)
+static void sl811_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
DBG(0, "sl811_cs_detach(0x%p)\n", link);
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- sl811_cs_release(link);
+ sl811_cs_release(link);
/* This points to the parent local_info_t struct */
kfree(link->priv);
}
-static void sl811_cs_release(dev_link_t * link)
+static void sl811_cs_release(struct pcmcia_device * link)
{
DBG(0, "sl811_cs_release(0x%p)\n", link);
- pcmcia_disable_device(link->handle);
+ pcmcia_disable_device(link);
platform_device_unregister(&platform_dev);
}
-static void sl811_cs_config(dev_link_t *link)
+static int sl811_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- client_handle_t handle = link->handle;
- struct device *parent = &handle_to_dev(handle);
- local_info_t *dev = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- cistpl_cftable_entry_t dflt = { 0 };
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+ return -ENODEV;
+ } else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
+ return -ENODEV;
+ }
- DBG(0, "sl811_cs_config(0x%p)\n", link);
+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
- tuple.DesiredTuple = CISTPL_CONFIG;
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
- link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(handle, &conf));
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-
- if (pcmcia_get_tuple_data(handle, &tuple) != 0
- || pcmcia_parse_tuple(handle, &tuple, &parse)
- != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
- dflt = *cfg;
- }
+ /* we need an interrupt */
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
- if (cfg->index == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = cfg->index;
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
- != conf.Vcc)
- goto next_entry;
- } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
- != conf.Vcc)
- goto next_entry;
- }
+ /* IO window settings */
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
- else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
-
- /* we need an interrupt */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
-
- /* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
-
- if (pcmcia_request_io(link->handle, &link->io) != 0)
- goto next_entry;
- }
- break;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
-next_entry:
- pcmcia_disable_device(handle);
- last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ return pcmcia_request_io(p_dev, &p_dev->io);
}
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+}
+
+
+static int sl811_cs_config(struct pcmcia_device *link)
+{
+ struct device *parent = &handle_to_dev(link);
+ local_info_t *dev = link->priv;
+ int last_fn, last_ret;
+
+ DBG(0, "sl811_cs_config(0x%p)\n", link);
+
+ if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
+ goto failed;
/* require an IRQ and two registers */
if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
- goto cs_failed;
+ goto failed;
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ,
- pcmcia_request_irq(link->handle, &link->irq));
+ pcmcia_request_irq(link, &link->irq));
else
- goto cs_failed;
+ goto failed;
CS_CHECK(RequestConfiguration,
- pcmcia_request_configuration(link->handle, &link->conf));
+ pcmcia_request_configuration(link, &link->conf));
sprintf(dev->node.dev_name, driver_name);
dev->node.major = dev->node.minor = 0;
link->io.BasePort1+link->io.NumPorts1-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
-
if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
< 0) {
cs_failed:
- printk("sl811_cs_config failed\n");
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
+failed:
+ printk(KERN_WARNING "sl811_cs_config failed\n");
sl811_cs_release(link);
- link->state &= ~DEV_CONFIG_PENDING;
+ return -ENODEV;
}
+ return 0;
}
-static int sl811_cs_attach(struct pcmcia_device *p_dev)
+static int sl811_cs_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link = dev_to_instance(p_dev);
- local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
return -ENOMEM;
- memset(local, 0, sizeof(local_info_t));
- local->p_dev = p_dev;
+ local->p_dev = link;
link->priv = local;
/* Initialize */
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sl811_cs_config(link);
-
- return 0;
+ return sl811_cs_config(link);
}
static struct pcmcia_device_id sl811_ids[] = {
.drv = {
.name = (char *)driver_name,
},
- .probe = sl811_cs_attach,
+ .probe = sl811_cs_probe,
.remove = sl811_cs_detach,
.id_table = sl811_ids,
};