Commit 00990e7c authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

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: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 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 @@ out_release:
======================================================================*/
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)))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment