event handler.
*/
-static void sedlbauer_config(dev_link_t *link);
-static void sedlbauer_release(dev_link_t *link);
+static int sedlbauer_config(struct pcmcia_device *link);
+static void sedlbauer_release(struct pcmcia_device *link);
/*
The attach() and detach() entry points are used to create and destroy
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
- in a linked list starting at the 'dev' field of a dev_link_t
+ in a linked list starting at the 'dev' field of a struct pcmcia_device
structure. We allocate them in the card's private data structure,
because they generally shouldn't be allocated dynamically.
*/
typedef struct local_info_t {
- dev_link_t link;
+ struct pcmcia_device *p_dev;
dev_node_t node;
int stop;
int cardnr;
======================================================================*/
-static int sedlbauer_attach(struct pcmcia_device *p_dev)
+static int sedlbauer_probe(struct pcmcia_device *link)
{
local_info_t *local;
- dev_link_t *link;
-
+
DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */
- 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->cardnr = -1;
- link = &local->link; link->priv = local;
-
+
+ local->p_dev = link;
+ link->priv = local;
+
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = 3;
-
link->conf.Attributes = 0;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->handle = p_dev;
- p_dev->instance = link;
-
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sedlbauer_config(link);
-
- return 0;
+ return sedlbauer_config(link);
} /* sedlbauer_attach */
/*======================================================================
======================================================================*/
-static void sedlbauer_detach(struct pcmcia_device *p_dev)
+static void sedlbauer_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
+ DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
- DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
-
- if (link->state & DEV_CONFIG) {
- ((local_info_t *)link->priv)->stop = 1;
- sedlbauer_release(link);
- }
+ ((local_info_t *)link->priv)->stop = 1;
+ sedlbauer_release(link);
- /* This points to the parent local_info_t struct */
- kfree(link->priv);
+ /* This points to the parent local_info_t struct */
+ kfree(link->priv);
} /* sedlbauer_detach */
/*======================================================================
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-static void sedlbauer_config(dev_link_t *link)
+static int sedlbauer_config(struct pcmcia_device *link)
{
- client_handle_t handle = link->handle;
local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
DEBUG(0, "sedlbauer_config(0x%p)\n", link);
- /*
- This reads the card's CONFIG tuple to find its configuration
- registers.
- */
- 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));
- link->conf.Vcc = conf.Vcc;
+ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
/*
In this loop, we scan the CIS for configuration table entries,
will only use the CIS to fill in implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t dflt = { 0 };
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
+ pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->conf.Vpp1 = link->conf.Vpp2 =
+ link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* Do we need to allocate an interrupt? */
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
/*
Now set up a common memory window, if needed. There is room
- in the dev_link_t structure for one memory window handle,
+ in the struct pcmcia_device structure for one memory window handle,
but if the base addresses need to be saved, or if multiple
windows are needed, the info should go in the private data
structure for this device.
req.Size = 0x1000;
*/
req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
}
/* If we got this far, we're cool! */
break;
-
+
next_entry:
-/* new in dummy.cs 2001/01/28 MN
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
-*/
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
-
+
/*
Allocate an interrupt line. Note that this does not assign a
handler to the interrupt, unless the 'Handler' member of the
irq structure is initialized.
*/
if (link->conf.Attributes & CONF_ENABLE_IRQ)
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
/*
This actually configures the PCMCIA socket -- setting up
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
/*
At this point, the dev_node_t structure(s) need to be
*/
sprintf(dev->node.dev_name, "sedlbauer");
dev->node.major = dev->node.minor = 0;
- link->dev = &dev->node;
+ link->dev_node = &dev->node;
/* Finally, report what we've done */
- printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
- dev->node.dev_name, link->conf.ConfigIndex,
- link->conf.Vcc/10, link->conf.Vcc%10);
- if (link->conf.Vpp1)
- printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(KERN_INFO "%s: index 0x%02x:",
+ dev->node.dev_name, link->conf.ConfigIndex);
+ if (link->conf.Vpp)
+ printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", mem 0x%06lx-0x%06lx", req.Base,
req.Base+req.Size-1);
printk("\n");
-
- link->state &= ~DEV_CONFIG_PENDING;
icard.para[0] = link->irq.AssignedIRQ;
icard.para[1] = link->io.BasePort1;
printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
last_ret, link->io.BasePort1);
sedlbauer_release(link);
+ return -ENODEV;
} else
((local_info_t*)link->priv)->cardnr = last_ret;
- return;
+ return 0;
cs_failed:
- cs_error(link->handle, last_fn, last_ret);
+ cs_error(link, last_fn, last_ret);
sedlbauer_release(link);
+ return -ENODEV;
} /* sedlbauer_config */
======================================================================*/
-static void sedlbauer_release(dev_link_t *link)
+static void sedlbauer_release(struct pcmcia_device *link)
{
local_info_t *local = link->priv;
DEBUG(0, "sedlbauer_release(0x%p)\n", link);
HiSax_closecard(local->cardnr);
}
}
- /* Unlink the device chain */
- link->dev = NULL;
- /*
- In a normal driver, additional code may be needed to release
- other kernel data structures associated with this device.
- */
-
- /* Don't bother checking to see if these succeed or not */
- if (link->win)
- pcmcia_release_window(link->win);
- pcmcia_release_configuration(link->handle);
- if (link->io.NumPorts1)
- pcmcia_release_io(link->handle, &link->io);
- if (link->irq.AssignedIRQ)
- pcmcia_release_irq(link->handle, &link->irq);
- link->state &= ~DEV_CONFIG;
+ pcmcia_disable_device(link);
} /* sedlbauer_release */
-static int sedlbauer_suspend(struct pcmcia_device *p_dev)
+static int sedlbauer_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state |= DEV_SUSPEND;
dev->stop = 1;
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
return 0;
}
-static int sedlbauer_resume(struct pcmcia_device *p_dev)
+static int sedlbauer_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
- link->state &= ~DEV_SUSPEND;
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
dev->stop = 0;
return 0;
.drv = {
.name = "sedlbauer_cs",
},
- .probe = sedlbauer_attach,
+ .probe = sedlbauer_probe,
.remove = sedlbauer_detach,
.id_table = sedlbauer_ids,
.suspend = sedlbauer_suspend,