提交 00990e7c 编写于 作者: D Dominik Brodowski

pcmcia: use autoconfiguration feature for ioports and iomem

When CONF_AUTO_SET_IO or CONF_AUTO_SET_IOMEM are set, the corresponding
fields in struct pcmcia_device *p_dev->resource[0,1,2] are set
accordinly. Drivers wishing to override certain settings may do so in
the callback function, but they no longer need to parse the CIS entries
stored in cistpl_cftable_entry_t themselves.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-ide@vger.kernel.org
CC: linux-usb@vger.kernel.org
CC: laforge@gnumonks.org
CC: linux-mtd@lists.infradead.org
CC: linux-bluetooth@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
CC: Jiri Kosina <jkosina@suse.cz>
CC: linux-scsi@vger.kernel.org
Tested-by: NWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: NDominik Brodowski <linux@dominikbrodowski.net>
上级 440eed43
This file details changes in 2.6 which affect PCMCIA card driver authors:
* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
If struct pcmcia_device *p_dev->config_flags is set accordingly,
pcmcia_loop_config() now sets up certain configuration values
automatically, though the driver may still override the settings
in the callback function. The following autoconfiguration options
are provided at the moment:
CONF_AUTO_CHECK_VCC : check for matching Vcc
CONF_AUTO_SET_VPP : set Vpp
CONF_AUTO_AUDIO : auto-enable audio line, if required
CONF_AUTO_SET_IO : set ioport resources (->resource[0,1])
CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])
* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
as it mirrors pcmcia_disable_device(). Configuration settings are now
......
......@@ -167,45 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
};
struct pcmcia_config_check {
unsigned long ctl_base;
int is_kme;
};
static int pcmcia_check_one_config(struct pcmcia_device *pdev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
struct pcmcia_config_check *stk = priv_data;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
pdev->resource[0]->start = io->win[0].base;
if (!(io->flags & CISTPL_IO_16BIT)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
}
if (io->nwin == 2) {
pdev->resource[0]->end = 8;
pdev->resource[1]->start = io->win[1].base;
pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[1]->start;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
pdev->resource[0]->end = io->win[0].len;
pdev->resource[1]->end = 0;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[0]->start + 0x0e;
} else
int *is_kme = priv_data;
if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
}
pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
if (pdev->resource[1]->end) {
pdev->resource[0]->end = 8;
pdev->resource[1]->end = (*is_kme) ? 2 : 1;
} else {
if (pdev->resource[0]->end < 16)
return -ENODEV;
/* If we've got this far, we're done */
return 0;
}
return -ENODEV;
return pcmcia_request_io(pdev);
}
/**
......@@ -220,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
{
struct ata_host *host;
struct ata_port *ap;
struct pcmcia_config_check *stk = NULL;
int is_kme = 0, ret = -ENOMEM, p;
unsigned long io_base, ctl_base;
void __iomem *io_addr, *ctl_addr;
......@@ -228,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
struct ata_port_operations *ops = &pcmcia_port_ops;
/* Set up attributes in order to probe card and get resources */
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
pdev->config_flags |= CONF_ENABLE_IRQ;
pdev->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
......@@ -239,21 +217,17 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));
/* Allocate resoure probing structures */
stk = kzalloc(sizeof(*stk), GFP_KERNEL);
if (!stk)
goto out1;
stk->is_kme = is_kme;
io_base = ctl_base = 0;
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
goto failed; /* No suitable config found */
}
io_base = pdev->resource[0]->start;
ctl_base = stk->ctl_base;
if (pdev->resource[1]->end)
ctl_base = pdev->resource[1]->start;
else
ctl_base = pdev->resource[0]->start + 0x0e;
if (!pdev->irq)
goto failed;
......@@ -310,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
goto failed;
pdev->priv = host;
kfree(stk);
return 0;
failed:
kfree(stk);
pcmcia_disable_device(pdev);
out1:
return ret;
}
......
......@@ -656,10 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_SET_IO;
return bt3c_config(link);
}
......@@ -673,38 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link)
kfree(info);
}
static int bt3c_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
unsigned long try = (unsigned long) priv_data;
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
int *try = priv_data;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
(cf->io.win[0].base != 0)) {
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
if (try == 0)
p_dev->io_lines = 16;
if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
return -EINVAL;
p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
return pcmcia_request_io(p_dev);
}
static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;
if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
if (p_dev->io_lines > 3)
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 8;
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
......
......@@ -585,10 +585,8 @@ static int btuart_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_SET_IO;
return btuart_config(link);
}
......@@ -602,38 +600,41 @@ static void btuart_detach(struct pcmcia_device *link)
kfree(info);
}
static int btuart_check_config(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
int *try = priv_data;
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
(cf->io.win[0].base != 0)) {
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
if (try == 0)
p_dev->io_lines = 16;
if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
return -EINVAL;
p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
return pcmcia_request_io(p_dev);
}
static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;
if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
if (p_dev->io_lines > 3)
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 8;
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
......
......@@ -571,10 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return dtl1_config(link);
}
......@@ -589,17 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link)
kfree(info);
}
static int dtl1_confcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
{
if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
return -ENODEV;
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->resource[0]->end = cf->io.win[0].len; /*yo */
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
return pcmcia_request_io(p_dev);
}
......
......@@ -1741,19 +1741,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
/*==== Interface to PCMCIA Layer =======================================*/
static int cm4000_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (!cfg->io.nwin)
return -ENODEV;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
return pcmcia_request_io(p_dev);
}
......@@ -1761,6 +1750,8 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;
link->config_flags |= CONF_AUTO_SET_IO;
/* read the config-tuples */
if (pcmcia_loop_config(link, cm4000_config_check, NULL))
goto cs_release;
......
......@@ -515,25 +515,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return;
}
static int cm4040_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int rc;
if (!cfg->io.nwin)
return -ENODEV;
/* Get the IOaddr */
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
rc = pcmcia_request_io(p_dev);
dev_printk(KERN_INFO, &p_dev->dev,
"pcmcia_request_io returned 0x%x\n", rc);
return rc;
return pcmcia_request_io(p_dev);
}
......@@ -542,6 +526,8 @@ static int reader_config(struct pcmcia_device *link, int devno)
struct reader_dev *dev;
int fail_rc;
link->config_flags |= CONF_AUTO_SET_IO;
if (pcmcia_loop_config(link, cm4040_config_check, NULL))
goto cs_release;
......
......@@ -75,22 +75,18 @@ static void signalled_reboot_callback(void *callback_data)
schedule_work(&ipw->work_reboot);
}
static int ipwireless_probe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
{
struct ipw_dev *ipw = priv_data;
struct resource *io_resource;
int ret;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
/* 0x40 causes it to generate level mode interrupts. */
/* 0x04 enables IREQ pin. */
p_dev->config_index = cfg->index | 0x44;
p_dev->config_index |= 0x44;
p_dev->io_lines = 16;
ret = pcmcia_request_io(p_dev);
if (ret)
......@@ -100,26 +96,18 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
resource_size(p_dev->resource[0]),
IPWIRELESS_PCCARD_NAME);
if (cfg->mem.nwin == 0)
return 0;
p_dev->resource[2]->flags |=
WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
p_dev->resource[2]->start = cfg->mem.win[0].host_addr;
p_dev->resource[2]->end = cfg->mem.win[0].len;
if (p_dev->resource[2]->end < 0x1000)
p_dev->resource[2]->end = 0x1000;
ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
if (ret != 0)
goto exit1;
ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2],
cfg->mem.win[0].card_addr);
ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
if (ret != 0)
goto exit2;
ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
ipw->attr_memory = ioremap(p_dev->resource[2]->start,
resource_size(p_dev->resource[2]));
......@@ -165,13 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
int ret = 0;
ipw->is_v2_card = 0;
link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
CONF_ENABLE_IRQ;
ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
if (ret != 0)
return ret;
link->config_flags |= CONF_ENABLE_IRQ;
INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
......
......@@ -561,19 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Card has been inserted.
*/
static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
if (!cfg->io.nwin)
return -ENODEV;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
return pcmcia_request_io(p_dev);
}
......@@ -585,11 +574,12 @@ static int mgslpc_config(struct pcmcia_device *link)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_config(0x%p)\n", link);
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
if (ret != 0)
goto failed;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_index = 8;
link->config_regs = PRESENT_OPTION;
......
......@@ -96,10 +96,8 @@ static int ide_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
return ide_config(link);
} /* ide_attach */
......@@ -194,52 +192,31 @@ static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
======================================================================*/
struct pcmcia_config_check {
unsigned long ctl_base;
int is_kme;
};
static int pcmcia_check_one_config(struct pcmcia_device *pdev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
{
struct pcmcia_config_check *stk = priv_data;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
pdev->config_index = cfg->index;
pdev->resource[0]->start = io->win[0].base;
if (!(io->flags & CISTPL_IO_16BIT)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
}
if (io->nwin == 2) {
pdev->resource[0]->end = 8;
pdev->resource[1]->start = io->win[1].base;
pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[1]->start;
} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
pdev->resource[0]->end = io->win[0].len;
pdev->resource[1]->end = 0;
if (pcmcia_request_io(pdev) != 0)
return -ENODEV;
stk->ctl_base = pdev->resource[0]->start + 0x0e;
} else
int *is_kme = priv_data;
if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
}
pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
if (pdev->resource[1]->end) {
pdev->resource[0]->end = 8;
pdev->resource[1]->end = (*is_kme) ? 2 : 1;
} else {
if (pdev->resource[0]->end < 16)
return -ENODEV;
/* If we've got this far, we're done */
return 0;
}
return -ENODEV;
return pcmcia_request_io(pdev);
}
static int ide_config(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
struct pcmcia_config_check *stk = NULL;
int ret = 0, is_kme = 0;
unsigned long io_base, ctl_base;
struct ide_host *host;
......@@ -250,19 +227,16 @@ static int ide_config(struct pcmcia_device *link)
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
stk = kzalloc(sizeof(*stk), GFP_KERNEL);
if (!stk)
goto err_mem;
stk->is_kme = is_kme;
io_base = ctl_base = 0;
if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
link->config_flags &= ~CONF_AUTO_CHECK_VCC;
if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
goto failed; /* No suitable config found */
}
io_base = link->resource[0]->start;
ctl_base = stk->ctl_base;
if (link->resource[1]->end)
ctl_base = link->resource[1]->start;
else
ctl_base = link->resource[0]->start + 0x0e;
if (!link->irq)
goto failed;
......@@ -294,15 +268,9 @@ static int ide_config(struct pcmcia_device *link)
'a' + host->ports[0]->index * 2,
link->vpp / 10, link->vpp % 10);
kfree(stk);
return 0;
err_mem:
printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
goto failed;
failed:
kfree(stk);
ide_release(link);
return -ENODEV;
} /* ide_config */
......
......@@ -72,13 +72,8 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
static int avmcs_probe(struct pcmcia_device *p_dev)
{
/* The io structure describes IO port mapping */
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
/* General socket configuration */
p_dev->config_flags |= CONF_ENABLE_IRQ;
p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
p_dev->config_index = 1;
p_dev->config_regs = PRESENT_OPTION;
......@@ -107,16 +102,12 @@ static void avmcs_detach(struct pcmcia_device *link)
======================================================================*/
static int avmcs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
if (cf->io.nwin <= 0)
return -ENODEV;
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->resource[0]->end = cf->io.win[0].len;
return pcmcia_request_io(p_dev);
}
......
......@@ -76,14 +76,8 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
{
dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
/* The io structure describes IO port mapping */
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[1]->end = 16;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
/* General socket configuration */
p_dev->config_flags |= CONF_ENABLE_IRQ;
p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
p_dev->config_index = 1;
p_dev->config_regs = PRESENT_OPTION;
......@@ -114,17 +108,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
======================================================================*/
static int avma1cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
if (cf->io.nwin <= 0)
return -ENODEV;
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->resource[0]->end = cf->io.win[0].len;
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->io_lines = 5;
return pcmcia_request_io(p_dev);
}
......
......@@ -118,16 +118,6 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
local->cardnr = -1;
/*
General socket configuration defaults can go here. In this
client, we assume very little, and rely on the CIS for almost
everything. In most clients, many details (i.e., number, sizes,
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
link->resource[0]->end = 8;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
return elsa_cs_config(link);
} /* elsa_cs_attach */
......@@ -160,18 +150,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
======================================================================*/
static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int j;
p_dev->io_lines = 3;
p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if ((cf->io.nwin > 0) && cf->io.win[0].base) {
if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
} else {
......@@ -194,6 +183,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
dev = link->priv;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
if (i != 0)
goto failed;
......
......@@ -128,8 +128,6 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
/* from old sedl_cs
*/
/* The io structure describes IO port mapping */
link->resource[0]->end = 8;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
return sedlbauer_config(link);
} /* sedlbauer_attach */
......@@ -161,35 +159,13 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
device available to the system.
======================================================================*/
static int sedlbauer_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
p_dev->io_lines = 3;
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
}
if (p_dev->config_index == 0)
return -EINVAL;
return 0;
p_dev->io_lines = 3;
return pcmcia_request_io(p_dev);
}
......@@ -202,7 +178,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
/*
In this loop, we scan the CIS for configuration table entries,
......
......@@ -105,10 +105,7 @@ static int __devinit teles_probe(struct pcmcia_device *link)
and attributes of IO windows) are fixed by the nature of the
device, and can be hard-wired here.
*/
link->resource[0]->end = 96;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return teles_cs_config(link);
} /* teles_attach */
......@@ -142,18 +139,17 @@ static void __devexit teles_detach(struct pcmcia_device *link)
======================================================================*/
static int teles_cs_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int j;
p_dev->io_lines = 5;
p_dev->resource[0]->end = 96;
p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if ((cf->io.nwin > 0) && cf->io.win[0].base) {
if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
} else {
......
......@@ -284,34 +284,16 @@ static int try_io_port(struct pcmcia_device *link)
}
}
static int axnet_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int i;
cistpl_io_t *io = &cfg->io;
if (cfg->index == 0 || cfg->io.nwin == 0)
return -ENODEV;
if (p_dev->config_index == 0)
return -EINVAL;
p_dev->config_index = 0x05;
/* For multifunction cards, by convention, we configure the
network function with window 0, and serial with window 1 */
if (io->nwin > 1) {
i = (io->win[1].len > io->win[0].len);
p_dev->resource[1]->start = io->win[1-i].base;
p_dev->resource[1]->end = io->win[1-i].len;
} else {
i = p_dev->resource[1]->end = 0;
}
p_dev->resource[0]->start = io->win[i].base;
p_dev->resource[0]->end = io->win[i].len;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
return try_io_port(p_dev);
if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
return -ENODEV;
return -ENODEV;
return try_io_port(p_dev);
}
static int axnet_config(struct pcmcia_device *link)
......@@ -324,6 +306,7 @@ static int axnet_config(struct pcmcia_device *link)
/* don't trust the CIS on this; Linksys got it wrong */
link->config_regs = 0x63;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
if (ret != 0)
goto failed;
......@@ -331,7 +314,6 @@ static int axnet_config(struct pcmcia_device *link)
if (!link->irq)
goto failed;
link->config_flags |= CONF_ENABLE_IRQ;
if (resource_size(link->resource[1]) == 8)
link->config_flags |= CONF_ENABLE_SPKR;
......
......@@ -319,10 +319,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
return ret; /* RequestIO failed */
}
static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
return 0; /* strange, but that's what the code did already before... */
}
......
......@@ -259,7 +259,7 @@ static int pcnet_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = dev;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
dev->netdev_ops = &pcnet_netdev_ops;
......@@ -500,42 +500,22 @@ static int try_io_port(struct pcmcia_device *link)
}
}
static int pcnet_confcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
{
int *priv = priv_data;
int try = (*priv & 0x1);
int i;
cistpl_io_t *io = &cfg->io;
if (cfg->index == 0 || cfg->io.nwin == 0)
return -EINVAL;
*priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
/* For multifunction cards, by convention, we configure the
network function with window 0, and serial with window 1 */
if (io->nwin > 1) {
i = (io->win[1].len > io->win[0].len);
p_dev->resource[1]->start = io->win[1-i].base;
p_dev->resource[1]->end = io->win[1-i].len;
} else {
i = p_dev->resource[1]->end = 0;
}
if (p_dev->config_index == 0)
return -EINVAL;
*priv &= ((cfg->mem.nwin == 1) &&
(cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
return -EINVAL;
p_dev->resource[0]->start = io->win[i].base;
p_dev->resource[0]->end = io->win[i].len;
if (!try)
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
else
if (try)
p_dev->io_lines = 16;
if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
return try_io_port(p_dev);
return -EINVAL;
return try_io_port(p_dev);
}
static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
......
......@@ -323,9 +323,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
link->priv = dev;
spin_lock_init(&smc->lock);
link->resource[0]->end = 16;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
/* The SMC91c92-specific entries in the device structure. */
dev->netdev_ops = &smc_netdev_ops;
......@@ -417,18 +414,21 @@ static int mhz_3288_power(struct pcmcia_device *link)
return 0;
}
static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int k;
p_dev->resource[1]->start = cf->io.win[0].base;
p_dev->io_lines = 16;
p_dev->resource[1]->start = p_dev->resource[0]->start;
p_dev->resource[1]->end = 8;
p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
for (k = 0; k < 0x400; k += 0x10) {
if (k & 0x80)
continue;
p_dev->resource[0]->start = k ^ 0x300;
p_dev->io_lines = 16;
if (!pcmcia_request_io(p_dev))
return 0;
}
......@@ -442,9 +442,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
unsigned int offset;
int i;
link->config_flags |= CONF_ENABLE_SPKR;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[1]->end = 8;
link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ |
CONF_AUTO_SET_IO;
/* The Megahertz combo cards have modem-like CIS entries, so
we have to explicitly try a bunch of port combinations. */
......@@ -586,13 +585,12 @@ static int mot_setup(struct pcmcia_device *link)
/*====================================================================*/
static int smc_configcheck(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->end = 16;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
return pcmcia_request_io(p_dev);
}
......@@ -601,7 +599,8 @@ static int smc_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
int i;
link->resource[0]->end = 16;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
i = pcmcia_loop_config(link, smc_configcheck, NULL);
if (!i)
dev->base_addr = link->resource[0]->start;
......@@ -634,7 +633,7 @@ static int osi_config(struct pcmcia_device *link)
static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int i, j;
link->config_flags |= CONF_ENABLE_SPKR;
link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ;
link->resource[0]->end = 64;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[1]->end = 8;
......
......@@ -528,7 +528,6 @@ xirc2ps_probe(struct pcmcia_device *link)
link->priv = dev;
/* General socket configuration */
link->config_flags |= CONF_ENABLE_IRQ;
link->config_index = 1;
/* Fill in card specific entries */
......@@ -665,42 +664,53 @@ has_ce2_string(struct pcmcia_device * p_dev)
}
static int
xirc2ps_config_modem(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data)
{
unsigned int ioaddr;
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
p_dev->resource[1]->start = cf->io.win[0].base;
p_dev->resource[0]->start = ioaddr;
if (!pcmcia_request_io(p_dev))
return 0;
}
if ((p_dev->resource[0]->start & 0xf) == 8)
return -ENODEV;
p_dev->resource[0]->end = 16;
p_dev->resource[1]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->io_lines = 10;
p_dev->resource[1]->start = p_dev->resource[0]->start;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
p_dev->resource[0]->start = ioaddr;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
static int
xirc2ps_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int *pass = priv_data;
resource_size_t tmp = p_dev->resource[1]->start;
if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
p_dev->resource[1]->start = cf->io.win[0].base;
p_dev->resource[0]->start = p_dev->resource[1]->start
+ (*pass ? (cf->index & 0x20 ? -24:8)
: (cf->index & 0x20 ? 8:-24));
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8)
: (p_dev->config_index & 0x20 ? 8 : -24));
if ((p_dev->resource[0]->start & 0xf) == 8)
return -ENODEV;
p_dev->resource[0]->end = 18;
p_dev->resource[1]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->io_lines = 10;
p_dev->resource[1]->start = p_dev->resource[0]->start;
p_dev->resource[0]->start = tmp;
return pcmcia_request_io(p_dev);
}
......@@ -803,21 +813,16 @@ xirc2ps_config(struct pcmcia_device * link)
goto failure;
}
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
link->io_lines = 10;
if (local->modem) {
int pass;
link->config_flags |= CONF_AUTO_SET_IO;
link->resource[1]->end = 8;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
if (local->dingo) {
/* Take the Modem IO port from the CIS and scan for a free
* Ethernet port */
link->resource[0]->end = 16; /* no Mako stuff anymore */
if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
goto port_found;
} else {
link->resource[0]->end = 18;
/* We do 2 passes here: The first one uses the regular mapping and
* the second tries again, thereby considering that the 32 ports are
* mirrored every 32 bytes. Actually we use a mirrored port for
......@@ -833,7 +838,9 @@ xirc2ps_config(struct pcmcia_device * link)
}
printk(KNOT_XIRC "no ports available\n");
} else {
link->io_lines = 10;
link->resource[0]->end = 16;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
link->resource[0]->start = ioaddr;
if (!(err = pcmcia_request_io(link)))
......
......@@ -137,36 +137,12 @@ static void airo_detach(struct pcmcia_device *link)
======================================================================*/
static int airo_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
if (p_dev->config_index == 0)
return -EINVAL;
/* If we got this far, we're cool! */
return 0;
return pcmcia_request_io(p_dev);
}
......@@ -180,7 +156,7 @@ static int airo_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "airo_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_AUDIO;
CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
/*
* In this loop, we scan the CIS for configuration table
......
......@@ -154,31 +154,11 @@ static int card_present(void *arg)
return 0;
}
static int atmel_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
}
if (p_dev->config_index == 0)
return -EINVAL;
/* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
......@@ -194,7 +174,7 @@ static int atmel_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "atmel_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_AUDIO;
CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
/*
In this loop, we scan the CIS for configuration table entries,
......
......@@ -469,46 +469,11 @@ static void prism2_detach(struct pcmcia_device *link)
/* run after a CARD_INSERTION event is received to configure the PCMCIA
* socket and make the device available to the system */
static int prism2_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
"(default 0x%02X)\n", cfg->index, dflt->index);
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
"dflt->io.nwin=%d\n",
cfg->io.nwin, dflt->io.nwin);
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
}
if (p_dev->config_index == 0)
return -EINVAL;
/* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
......@@ -531,7 +496,7 @@ static int prism2_config(struct pcmcia_device *link)
/* Look for an appropriate configuration table entry in the CIS */
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
CONF_AUTO_CHECK_VCC;
CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
if (ignore_cis_vcc)
link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, prism2_config_check, NULL);
......
......@@ -794,20 +794,12 @@ static void if_cs_release(struct pcmcia_device *p_dev)
* insertion event.
*/
static int if_cs_ioprobe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
if (cfg->io.nwin != 1) {
if (p_dev->resource[1]->end) {
lbs_pr_err("wrong CIS (check number of IO windows)\n");
return -ENODEV;
}
......@@ -833,6 +825,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
card->p_dev = p_dev;
p_dev->priv = card;
p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
lbs_pr_err("error in pcmcia_loop_config\n");
goto out1;
......
......@@ -142,42 +142,12 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
* device available to the system.
*/
static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
goto next_entry;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
goto next_entry;
}
return 0;
if (p_dev->config_index == 0)
return -EINVAL;
next_entry:
pcmcia_disable_device(p_dev);
return -ENODEV;
return pcmcia_request_io(p_dev);
};
static int
......@@ -202,7 +172,8 @@ orinoco_cs_config(struct pcmcia_device *link)
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
if (ignore_cis_vcc)
link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
......
......@@ -205,48 +205,12 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
*/
static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
goto next_entry;
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
p_dev->vpp =
dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
goto next_entry;
}
return 0;
if (p_dev->config_index == 0)
return -EINVAL;
next_entry:
pcmcia_disable_device(p_dev);
return -ENODEV;
return pcmcia_request_io(p_dev);
};
static int
......@@ -271,7 +235,8 @@ spectrum_cs_config(struct pcmcia_device *link)
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
if (ignore_cis_vcc)
link->config_flags &= ~CONF_AUTO_CHECK_VCC;
ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
......
......@@ -100,9 +100,7 @@ static int parport_probe(struct pcmcia_device *link)
link->priv = info;
info->p_dev = link;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return parport_config(link);
} /* parport_attach */
......@@ -133,27 +131,14 @@ static void parport_detach(struct pcmcia_device *link)
======================================================================*/
static int parport_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
if (epp_mode)
p_dev->config_index |= FORCE_EPP_MODE;
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin == 2) {
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
return 0;
}
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
return pcmcia_request_io(p_dev);
}
static int parport_config(struct pcmcia_device *link)
......@@ -164,6 +149,9 @@ static int parport_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "parport_config\n");
if (epp_mode)
link->config_index |= FORCE_EPP_MODE;
ret = pcmcia_loop_config(link, parport_config_check, NULL);
if (ret)
goto failed;
......
......@@ -6,7 +6,7 @@
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Copyright (C) 1999 David A. Hinds
* Copyright (C) 2004-2009 Dominik Brodowski
* Copyright (C) 2004-2010 Dominik Brodowski
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -125,13 +125,24 @@ int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function,
return ret;
}
/**
* pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
*/
static int pcmcia_io_cfg_data_width(unsigned int flags)
{
if (!(flags & CISTPL_IO_8BIT))
return IO_DATA_PATH_WIDTH_16;
if (!(flags & CISTPL_IO_16BIT))
return IO_DATA_PATH_WIDTH_8;
return IO_DATA_PATH_WIDTH_AUTO;
}
struct pcmcia_cfg_mem {
struct pcmcia_device *p_dev;
int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
void *priv_data;
int (*conf_check) (struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data);
cisparse_t parse;
cistpl_cftable_entry_t dflt;
};
......@@ -184,16 +195,63 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
p_dev->config_flags |= CONF_ENABLE_SPKR;
return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
cfg_mem->priv_data);
/* IO window settings? */
if (flags & CONF_AUTO_SET_IO) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
int i = 0;
p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
if (io->nwin == 0)
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
if (io->nwin > 1) {
/* For multifunction cards, by convention, we
* configure the network function with window 0,
* and serial with window 1 */
i = (io->win[1].len > io->win[0].len);
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1-i].base;
p_dev->resource[1]->end = io->win[1-i].len;
}
p_dev->resource[0]->start = io->win[i].base;
p_dev->resource[0]->end = io->win[i].len;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
}
/* MEM window settings? */
if (flags & CONF_AUTO_SET_IOMEM) {
/* so far, we only set one memory window */
cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
if (mem->nwin == 0)
return -ENODEV;
p_dev->resource[2]->start = mem->win[0].host_addr;
p_dev->resource[2]->end = mem->win[0].len;
if (p_dev->resource[2]->end < 0x1000)
p_dev->resource[2]->end = 0x1000;
p_dev->card_addr = mem->win[0].card_addr;
}
dev_dbg(&p_dev->dev,
"checking configuration %x: %pr %pr %pr (%d lines)\n",
p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
p_dev->resource[2], p_dev->io_lines);
return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
}
/**
* pcmcia_loop_config() - loop over configuration options
* @p_dev: the struct pcmcia_device which we need to loop for.
* @conf_check: function to call for each configuration option.
* It gets passed the struct pcmcia_device, the CIS data
* describing the configuration option, and private data
* It gets passed the struct pcmcia_device and private data
* being passed to pcmcia_loop_config()
* @priv_data: private data to be passed to the conf_check function.
*
......@@ -203,8 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
*/
int pcmcia_loop_config(struct pcmcia_device *p_dev,
int (*conf_check) (struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data),
void *priv_data)
{
......
......@@ -99,9 +99,7 @@ static int aha152x_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->end = 0x20;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
link->config_regs = PRESENT_OPTION;
return aha152x_config_cs(link);
......@@ -121,24 +119,24 @@ static void aha152x_detach(struct pcmcia_device *link)
/*====================================================================*/
static int aha152x_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
/* For New Media T&J, look for a SCSI window */
if (cfg->io.win[0].len >= 0x20)
p_dev->resource[0]->start = cfg->io.win[0].base;
else if ((cfg->io.nwin > 1) &&
(cfg->io.win[1].len >= 0x20))
p_dev->resource[0]->start = cfg->io.win[1].base;
if ((cfg->io.nwin > 0) &&
(p_dev->resource[0]->start < 0xffff)) {
if (!pcmcia_request_io(p_dev))
return 0;
}
return -EINVAL;
if ((p_dev->resource[0]->end < 0x20) &&
(p_dev->resource[1]->end >= 0x20))
p_dev->resource[0]->start = p_dev->resource[1]->start;
if (p_dev->resource[0]->start >= 0xffff)
return -EINVAL;
p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
p_dev->resource[0]->end = 0x20;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
return pcmcia_request_io(p_dev);
}
static int aha152x_config_cs(struct pcmcia_device *link)
......
......@@ -82,9 +82,7 @@ static int fdomain_probe(struct pcmcia_device *link)
info->p_dev = link;
link->priv = info;
link->resource[0]->end = 0x10;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
link->config_regs = PRESENT_OPTION;
return fdomain_config(link);
......@@ -103,13 +101,12 @@ static void fdomain_detach(struct pcmcia_device *link)
/*====================================================================*/
static int fdomain_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = 0x10;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
return pcmcia_request_io(p_dev);
}
......
......@@ -1556,13 +1556,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
/* The io structure describes IO port mapping */
link->resource[0]->end = 0x10;
link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
/* General socket configuration */
link->config_flags |= CONF_ENABLE_IRQ;
ret = nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
......@@ -1594,50 +1587,27 @@ static void nsp_cs_detach(struct pcmcia_device *link)
ethernet device available to the system.
======================================================================*/
static int nsp_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
nsp_hw_data *data = priv_data;
if (cfg->index == 0)
if (p_dev->config_index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
goto next_entry;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
goto next_entry;
if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
cistpl_mem_t *mem =
(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
if (resource_size(p_dev->resource[2])) {
p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
WIN_MEMORY_TYPE_CM |
WIN_ENABLE);
p_dev->resource[2]->start = mem->win[0].host_addr;
p_dev->resource[2]->end = mem->win[0].len;
if (p_dev->resource[2]->end < 0x1000)
p_dev->resource[2]->end = 0x1000;
if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
goto next_entry;
if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
mem->win[0].card_addr) != 0)
p_dev->card_addr) != 0)
goto next_entry;
data->MmioAddress = (unsigned long)
......@@ -1664,7 +1634,8 @@ static int nsp_cs_config(struct pcmcia_device *link)
nsp_dbg(NSP_DEBUG_INIT, "in");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |
CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
if (ret)
......
......@@ -155,9 +155,7 @@ static int qlogic_probe(struct pcmcia_device *link)
return -ENOMEM;
info->p_dev = link;
link->priv = info;
link->resource[0]->end = 16;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
link->config_regs = PRESENT_OPTION;
return qlogic_config(link);
......@@ -176,14 +174,11 @@ static void qlogic_detach(struct pcmcia_device *link)
/*====================================================================*/
static int qlogic_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if (p_dev->resource[0]->start == 0)
return -ENODEV;
......
......@@ -683,14 +683,11 @@ static struct scsi_host_template sym53c500_driver_template = {
.shost_attrs = SYM53C500_shost_attrs
};
static int SYM53C500_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
p_dev->io_lines = 10;
p_dev->resource[0]->start = cfg->io.win[0].base;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
if (p_dev->resource[0]->start == 0)
return -ENODEV;
......@@ -857,9 +854,7 @@ SYM53C500_probe(struct pcmcia_device *link)
return -ENOMEM;
info->p_dev = link;
link->priv = info;
link->resource[0]->end = 16;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
link->config_flags |= CONF_ENABLE_IRQ;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
return SYM53C500_config(link);
} /* SYM53C500_attach */
......
......@@ -424,41 +424,45 @@ static int pfc_config(struct pcmcia_device *p_dev)
return -ENODEV;
}
static int simple_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
static const int size_table[2] = { 8, 16 };
int *try = priv_data;
p_dev->io_lines = ((*try & 0x1) == 0) ?
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
if (p_dev->resource[0]->start == 0)
return -ENODEV;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
&& (cf->io.win[0].base != 0)) {
p_dev->resource[0]->start = cf->io.win[0].base;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -EINVAL;
if ((*try & 0x1) == 0)
p_dev->io_lines = 16;
if (p_dev->resource[0]->end != size_table[(*try >> 1)])
return -ENODEV;
p_dev->resource[0]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
return pcmcia_request_io(p_dev);
}
static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
int j;
if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
if (p_dev->io_lines > 3)
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = 8;
for (j = 0; j < 5; j++) {
p_dev->resource[0]->start = base[j];
p_dev->io_lines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
}
......@@ -468,12 +472,9 @@ static int simple_config(struct pcmcia_device *link)
struct serial_info *info = link->priv;
int i = -ENODEV, try;
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = 8;
/* First pass: look for a config entry that looks normal.
* Two tries: without IO aliases, then with aliases */
link->config_flags |= CONF_AUTO_SET_VPP;
link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO;
for (try = 0; try < 4; try++)
if (!pcmcia_loop_config(link, simple_config_check, &try))
goto found_port;
......@@ -503,43 +504,44 @@ static int simple_config(struct pcmcia_device *link)
return setup_serial(link, info, link->resource[0]->start, link->irq);
}
static int multi_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
int *base2 = priv_data;
int *multi = priv_data;
if (p_dev->resource[1]->end)
return -EINVAL;
/* The quad port cards have bad CIS's, so just look for a
window larger than 8 ports and assume it will be right */
if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
if (!pcmcia_request_io(p_dev)) {
*base2 = p_dev->resource[0]->start + 8;
return 0;
}
}
return -ENODEV;
if (p_dev->resource[0]->end <= 8)
return -EINVAL;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->end = *multi * 8;
if (pcmcia_request_io(p_dev))
return -ENODEV;
return 0;
}
static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
int *base2 = priv_data;
if (cf->io.nwin == 2) {
p_dev->resource[0]->start = cf->io.win[0].base;
p_dev->resource[1]->start = cf->io.win[1].base;
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
if (!pcmcia_request_io(p_dev)) {
*base2 = p_dev->resource[1]->start;
return 0;
}
}
return -ENODEV;
if (!p_dev->resource[0]->end || !p_dev->resource[1]->end)
return -ENODEV;
p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
if (pcmcia_request_io(p_dev))
return -ENODEV;
*base2 = p_dev->resource[0]->start + 8;
return 0;
}
static int multi_config(struct pcmcia_device *link)
......@@ -547,12 +549,12 @@ static int multi_config(struct pcmcia_device *link)
struct serial_info *info = link->priv;
int i, base2 = 0;
link->config_flags |= CONF_AUTO_SET_IO;
/* First, look for a generic full-sized window */
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
link->resource[0]->end = info->multi * 8;
if (pcmcia_loop_config(link, multi_config_check, &base2)) {
if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
base2 = link->resource[0]->start + 8;
else {
/* If that didn't work, look for two windows */
link->resource[0]->end = link->resource[1]->end = 8;
info->multi = 2;
if (pcmcia_loop_config(link, multi_config_check_notpicky,
&base2)) {
......@@ -587,7 +589,7 @@ static int multi_config(struct pcmcia_device *link)
link->config_index == 3) {
err = setup_serial(link, info, base2,
link->irq);
base2 = link->resource[0]->start;;
base2 = link->resource[0]->start;
} else {
err = setup_serial(link, info, link->resource[0]->start,
link->irq);
......@@ -611,18 +613,18 @@ static int multi_config(struct pcmcia_device *link)
return 0;
}
static int serial_check_for_multi(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data)
{
struct serial_info *info = p_dev->priv;
if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
info->multi = cf->io.win[0].len >> 3;
if (!p_dev->resource[0]->end)
return -EINVAL;
if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
info->multi = p_dev->resource[0]->end >> 3;
if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
(cf->io.win[1].len == 8))
if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
&& (p_dev->resource[1]->end == 8))
info->multi = 2;
return 0; /* break */
......
......@@ -710,36 +710,12 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
if (p_dev->config_index == 0)
return -EINVAL;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
return 0;
return pcmcia_request_io(p_dev);
}
static void das16cs_pcmcia_config(struct pcmcia_device *link)
......@@ -748,6 +724,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
/* Do we need to allocate an interrupt? */
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
if (ret) {
dev_warn(&link->dev, "no configuration found\n");
......
......@@ -192,35 +192,12 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
return 0;
if (p_dev->config_index == 0)
return -EINVAL;
return pcmcia_request_io(p_dev);
}
......@@ -238,6 +215,8 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "das08_pcmcia_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL);
if (ret) {
dev_warn(&link->dev, "no configuration found\n");
......
......@@ -530,35 +530,12 @@ static void dio700_cs_detach(struct pcmcia_device *link)
======================================================================*/
static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
}
if (p_dev->config_index == 0)
return -EINVAL;
/* If we got this far, we're cool! */
return 0;
return pcmcia_request_io(p_dev);
}
static void dio700_config(struct pcmcia_device *link)
......@@ -570,7 +547,8 @@ static void dio700_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "dio700_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
if (ret) {
......
......@@ -282,35 +282,12 @@ static void dio24_cs_detach(struct pcmcia_device *link)
======================================================================*/
static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
}
if (p_dev->config_index == 0)
return -EINVAL;
/* If we got this far, we're cool! */
return 0;
return pcmcia_request_io(p_dev);
}
static void dio24_config(struct pcmcia_device *link)
......@@ -321,7 +298,8 @@ static void dio24_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "dio24_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
if (ret) {
......
......@@ -261,35 +261,12 @@ static void labpc_cs_detach(struct pcmcia_device *link)
======================================================================*/
static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev) != 0)
return -ENODEV;
}
if (p_dev->config_index == 0)
return -EINVAL;
/* If we got this far, we're cool! */
return 0;
return pcmcia_request_io(p_dev);
}
......@@ -300,7 +277,7 @@ static void labpc_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "labpc_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
CONF_AUTO_AUDIO;
CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
if (ret) {
......@@ -316,7 +293,6 @@ static void labpc_config(struct pcmcia_device *link)
the I/O windows and the interrupt mapping, and putting the
card and host interface into "Memory and IO" mode.
*/
p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
ret = pcmcia_enable_device(link);
if (ret)
goto failed;
......
......@@ -262,10 +262,6 @@ static struct pcmcia_device *cur_dev = NULL;
static int cs_attach(struct pcmcia_device *link)
{
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
link->resource[0]->end = 16;
link->config_flags |= CONF_ENABLE_IRQ;
cur_dev = link;
mio_cs_config(link);
......@@ -299,15 +295,12 @@ static int mio_cs_resume(struct pcmcia_device *link)
}
static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
{
int base, ret;
p_dev->resource[0]->end = cfg->io.win[0].len;
p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
for (base = 0x000; base < 0x400; base += 0x20) {
p_dev->resource[0]->start = base;
......@@ -324,6 +317,7 @@ static void mio_cs_config(struct pcmcia_device *link)
int ret;
DPRINTK("mio_cs_config(link=%p)\n", link);
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
if (ret) {
......
......@@ -1068,35 +1068,11 @@ static void daqp_cs_detach(struct pcmcia_device *link)
======================================================================*/
static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
if (p_dev->config_index == 0)
return -EINVAL;
/* Do we need to allocate an interrupt? */
p_dev->config_flags |= CONF_ENABLE_IRQ;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |=
pcmcia_io_cfg_data_width(io->flags);
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
if (io->nwin > 1) {
p_dev->resource[1]->flags = p_dev->resource[0]->flags;
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
}
/* This reserves IO space but doesn't actually enable it */
return pcmcia_request_io(p_dev);
}
......@@ -1106,6 +1082,8 @@ static void daqp_cs_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "daqp_cs_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL);
if (ret) {
dev_warn(&link->dev, "no configuration found\n");
......
......@@ -31,8 +31,6 @@ static int ixj_probe(struct pcmcia_device *p_dev)
{
dev_dbg(&p_dev->dev, "ixj_attach()\n");
/* Create new ixj device */
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
if (!p_dev->priv) {
return -ENOMEM;
......@@ -109,36 +107,28 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
return;
}
static int ixj_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
p_dev->io_lines = 3;
if (io->nwin == 2) {
p_dev->resource[1]->start = io->win[1].base;
p_dev->resource[1]->end = io->win[1].len;
}
if (!pcmcia_request_io(p_dev))
return 0;
}
return -ENODEV;
p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->io_lines = 3;
return pcmcia_request_io(p_dev);
}
static int ixj_config(struct pcmcia_device * link)
{
IXJ *j;
ixj_info_t *info;
cistpl_cftable_entry_t dflt = { 0 };
info = link->priv;
dev_dbg(&link->dev, "ixj_config\n");
if (pcmcia_loop_config(link, ixj_config_check, &dflt))
link->config_flags = CONF_AUTO_SET_IO;
if (pcmcia_loop_config(link, ixj_config_check, NULL))
goto failed;
if (pcmcia_enable_device(link))
......
......@@ -131,28 +131,12 @@ static void sl811_cs_release(struct pcmcia_device * link)
platform_device_unregister(&platform_dev);
}
static int sl811_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt,
void *priv_data)
static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
if (cfg->index == 0)
return -ENODEV;
if (p_dev->config_index == 0)
return -EINVAL;
/* IO window settings */
p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
p_dev->resource[0]->start = io->win[0].base;
p_dev->resource[0]->end = io->win[0].len;
return pcmcia_request_io(p_dev);
}
pcmcia_disable_device(p_dev);
return -ENODEV;
return pcmcia_request_io(p_dev);
}
......@@ -164,7 +148,7 @@ static int sl811_cs_config(struct pcmcia_device *link)
dev_dbg(&link->dev, "sl811_cs_config\n");
link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
CONF_AUTO_CHECK_VCC;
CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO;
if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
goto failed;
......
......@@ -93,6 +93,7 @@ struct pcmcia_device {
/* device setup */
unsigned int irq;
struct resource *resource[PCMCIA_NUM_RESOURCES];
resource_size_t card_addr; /* for the 1st IOMEM resource */
unsigned int vpp;
unsigned int config_flags; /* CONF_ENABLE_ flags below */
......@@ -175,8 +176,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse);
/* loop CIS entries for valid configuration */
int pcmcia_loop_config(struct pcmcia_device *p_dev,
int (*conf_check) (struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
cistpl_cftable_entry_t *dflt,
void *priv_data),
void *priv_data);
......@@ -225,16 +224,6 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev);
#define IO_DATA_PATH_WIDTH_16 0x08
#define IO_DATA_PATH_WIDTH_AUTO 0x10
/* convert flag found in cfgtable to data path width parameter */
static inline int pcmcia_io_cfg_data_width(unsigned int flags)
{
if (!(flags & CISTPL_IO_8BIT))
return IO_DATA_PATH_WIDTH_16;
if (!(flags & CISTPL_IO_16BIT))
return IO_DATA_PATH_WIDTH_8;
return IO_DATA_PATH_WIDTH_AUTO;
}
/* IO memory */
#define WIN_MEMORY_TYPE_CM 0x00 /* default */
#define WIN_MEMORY_TYPE_AM 0x20 /* MAP_ATTRIB */
......@@ -264,16 +253,17 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
#define PRESENT_IOSIZE 0x200
/* flags to be passed to pcmcia_enable_device() */
#define CONF_ENABLE_IRQ 0x01
#define CONF_ENABLE_SPKR 0x02
#define CONF_ENABLE_PULSE_IRQ 0x04
#define CONF_ENABLE_ESR 0x08
#define CONF_ENABLE_IRQ 0x0001
#define CONF_ENABLE_SPKR 0x0002
#define CONF_ENABLE_PULSE_IRQ 0x0004
#define CONF_ENABLE_ESR 0x0008
/* flags used by pcmcia_loop_config() autoconfiguration */
#define CONF_AUTO_CHECK_VCC 0x10 /* check for matching Vcc? */
#define CONF_AUTO_SET_VPP 0x20 /* set Vpp? */
#define CONF_AUTO_AUDIO 0x40 /* enable audio line? */
#define CONF_AUTO_CHECK_VCC 0x0100 /* check for matching Vcc? */
#define CONF_AUTO_SET_VPP 0x0200 /* set Vpp? */
#define CONF_AUTO_AUDIO 0x0400 /* enable audio line? */
#define CONF_AUTO_SET_IO 0x0800 /* set ->resource[0,1] */
#define CONF_AUTO_SET_IOMEM 0x1000 /* set ->resource[2] */
#endif /* __KERNEL__ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册