dect
/
linux-2.6
Archived
13
0
Fork 0

pcmcia: use pcmcia_loop_config in scsi pcmcia drivers

Use the config loop helper in scsi pcmcia drivers.

CC: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
CC: linux-scsi@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
Dominik Brodowski 2008-07-29 08:38:55 +02:00
parent ed58872aa3
commit 0e6f9d2708
5 changed files with 203 additions and 218 deletions

View File

@ -140,44 +140,40 @@ static void aha152x_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int aha152x_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
/* For New Media T&J, look for a SCSI window */
if (cfg->io.win[0].len >= 0x20)
p_dev->io.BasePort1 = cfg->io.win[0].base;
else if ((cfg->io.nwin > 1) &&
(cfg->io.win[1].len >= 0x20))
p_dev->io.BasePort1 = cfg->io.win[1].base;
if ((cfg->io.nwin > 0) &&
(p_dev->io.BasePort1 < 0xffff)) {
p_dev->conf.ConfigIndex = cfg->index;
if (!pcmcia_request_io(p_dev, &p_dev->io))
return 0;
}
return -EINVAL;
}
static int aha152x_config_cs(struct pcmcia_device *link) static int aha152x_config_cs(struct pcmcia_device *link)
{ {
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
struct aha152x_setup s; struct aha152x_setup s;
tuple_t tuple; int last_ret, last_fn;
cisparse_t parse;
int i, last_ret, last_fn;
u_char tuple_data[64];
struct Scsi_Host *host; struct Scsi_Host *host;
DEBUG(0, "aha152x_config(0x%p)\n", link); DEBUG(0, "aha152x_config(0x%p)\n", link);
tuple.TupleData = tuple_data; last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL);
tuple.TupleDataMax = 64; if (last_ret) {
tuple.TupleOffset = 0; cs_error(link, RequestIO, last_ret);
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; goto failed;
tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
/* For New Media T&J, look for a SCSI window */
if (parse.cftable_entry.io.win[0].len >= 0x20)
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
else if ((parse.cftable_entry.io.nwin > 1) &&
(parse.cftable_entry.io.win[1].len >= 0x20))
link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
if ((parse.cftable_entry.io.nwin > 0) &&
(link->io.BasePort1 < 0xffff)) {
link->conf.ConfigIndex = parse.cftable_entry.index;
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
}
next_entry:
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
} }
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
@ -208,6 +204,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
cs_failed: cs_failed:
cs_error(link, last_fn, last_ret); cs_error(link, last_fn, last_ret);
failed:
aha152x_release_cs(link); aha152x_release_cs(link);
return -ENODEV; return -ENODEV;
} }

View File

@ -123,34 +123,29 @@ static void fdomain_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int fdomain_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
p_dev->conf.ConfigIndex = cfg->index;
p_dev->io.BasePort1 = cfg->io.win[0].base;
return pcmcia_request_io(p_dev, &p_dev->io);
}
static int fdomain_config(struct pcmcia_device *link) static int fdomain_config(struct pcmcia_device *link)
{ {
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
tuple_t tuple; int last_ret, last_fn;
cisparse_t parse;
int i, last_ret, last_fn;
u_char tuple_data[64];
char str[22]; char str[22];
struct Scsi_Host *host; struct Scsi_Host *host;
DEBUG(0, "fdomain_config(0x%p)\n", link); DEBUG(0, "fdomain_config(0x%p)\n", link);
tuple.TupleData = tuple_data; last_ret = pcmcia_loop_config(link, fdomain_config_check, NULL);
tuple.TupleDataMax = 64; if (last_ret) {
tuple.TupleOffset = 0; cs_error(link, RequestIO, last_ret);
goto failed;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS) break;
next_entry:
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
} }
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@ -181,6 +176,7 @@ static int fdomain_config(struct pcmcia_device *link)
cs_failed: cs_failed:
cs_error(link, last_fn, last_ret); cs_error(link, last_fn, last_ret);
failed:
fdomain_release(link); fdomain_release(link);
return -ENODEV; return -ENODEV;
} /* fdomain_config */ } /* fdomain_config */

View File

@ -1607,133 +1607,136 @@ static void nsp_cs_detach(struct pcmcia_device *link)
is received, to configure the PCMCIA socket, and to make the is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system. ethernet device available to the system.
======================================================================*/ ======================================================================*/
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) struct nsp_cs_configdata {
/*====================================================================*/ nsp_hw_data *data;
win_req_t req;
config_info_t conf;
cistpl_cftable_entry_t dflt;
};
static int nsp_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
struct nsp_cs_configdata *cfg_mem = priv_data;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
memcpy(&cfg_mem->dflt, cfg, sizeof(cistpl_cftable_entry_t));
if (cfg->index == 0)
return -ENODEV;
p_dev->conf.ConfigIndex = cfg->index;
/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
p_dev->conf.Status = CCSR_AUDIO_ENA;
}
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
return -ENODEV;
else if (cfg_mem->dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
return -ENODEV;
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
p_dev->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
} else if (cfg_mem->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
p_dev->conf.Vpp =
cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
/* Do we need to allocate an interrupt? */
if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1) {
p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
}
/* IO window settings */
p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io;
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
p_dev->io.BasePort1 = io->win[0].base;
p_dev->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
p_dev->io.Attributes2 = p_dev->io.Attributes1;
p_dev->io.BasePort2 = io->win[1].base;
p_dev->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
goto next_entry;
}
if ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) {
memreq_t map;
cistpl_mem_t *mem =
(cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem;
cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
cfg_mem->req.Attributes |= WIN_ENABLE;
cfg_mem->req.Base = mem->win[0].host_addr;
cfg_mem->req.Size = mem->win[0].len;
if (cfg_mem->req.Size < 0x1000)
cfg_mem->req.Size = 0x1000;
cfg_mem->req.AccessSpeed = 0;
if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
goto next_entry;
cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
cfg_mem->data->MmioLength = cfg_mem->req.Size;
}
/* If we got this far, we're cool! */
return 0;
}
next_entry:
nsp_dbg(NSP_DEBUG_INIT, "next");
pcmcia_disable_device(p_dev);
return -ENODEV;
}
static int nsp_cs_config(struct pcmcia_device *link) static int nsp_cs_config(struct pcmcia_device *link)
{ {
int ret; int ret;
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
tuple_t tuple; struct nsp_cs_configdata *cfg_mem;
cisparse_t parse;
int last_ret, last_fn;
unsigned char tuple_data[64];
config_info_t conf;
win_req_t req;
memreq_t map;
cistpl_cftable_entry_t dflt = { 0 };
struct Scsi_Host *host; struct Scsi_Host *host;
nsp_hw_data *data = &nsp_data_base; nsp_hw_data *data = &nsp_data_base;
nsp_dbg(NSP_DEBUG_INIT, "in"); nsp_dbg(NSP_DEBUG_INIT, "in");
tuple.Attributes = 0; cfg_mem = kzalloc(sizeof(cfg_mem), GFP_KERNEL);
tuple.TupleData = tuple_data; if (!cfg_mem)
tuple.TupleDataMax = sizeof(tuple_data); return -ENOMEM;
tuple.TupleOffset = 0; cfg_mem->data = data;
/* Look up the current Vcc */ /* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &cfg_mem->conf));
ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; goto cs_failed;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
if (cfg->index == 0) { goto next_entry; }
link->conf.ConfigIndex = cfg->index;
/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
goto next_entry;
}
} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
goto next_entry;
}
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
} else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
/* Do we need to allocate an interrupt? */
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
link->conf.Attributes |= CONF_ENABLE_IRQ;
}
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
link->io.Attributes2 = link->io.Attributes1;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
cistpl_mem_t *mem =
(cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
req.Attributes |= WIN_ENABLE;
req.Base = mem->win[0].host_addr;
req.Size = mem->win[0].len;
if (req.Size < 0x1000) {
req.Size = 0x1000;
}
req.AccessSpeed = 0;
if (pcmcia_request_window(&link, &req, &link->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
if (pcmcia_map_mem_page(link->win, &map) != 0)
goto next_entry;
data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
data->MmioLength = req.Size;
}
/* If we got this far, we're cool! */
break;
next_entry:
nsp_dbg(NSP_DEBUG_INIT, "next");
pcmcia_disable_device(link);
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
if (link->conf.Attributes & CONF_ENABLE_IRQ) { if (link->conf.Attributes & CONF_ENABLE_IRQ) {
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); if (pcmcia_request_irq(link, &link->irq))
goto cs_failed;
} }
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
goto cs_failed;
if (free_ports) { if (free_ports) {
if (link->io.BasePort1) { if (link->io.BasePort1) {
@ -1791,20 +1794,20 @@ static int nsp_cs_config(struct pcmcia_device *link)
printk(" & 0x%04x-0x%04x", link->io.BasePort2, printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1); link->io.BasePort2+link->io.NumPorts2-1);
if (link->win) if (link->win)
printk(", mem 0x%06lx-0x%06lx", req.Base, printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
req.Base+req.Size-1); cfg_mem->req.Base+cfg_mem->req.Size-1);
printk("\n"); printk("\n");
kfree(cfg_mem);
return 0; return 0;
cs_failed: cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail"); nsp_dbg(NSP_DEBUG_INIT, "config fail");
cs_error(link, last_fn, last_ret);
nsp_cs_release(link); nsp_cs_release(link);
kfree(cfg_mem);
return -ENODEV; return -ENODEV;
} /* nsp_cs_config */ } /* nsp_cs_config */
#undef CS_CHECK
/*====================================================================== /*======================================================================

View File

@ -195,39 +195,32 @@ static void qlogic_detach(struct pcmcia_device *link)
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int qlogic_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
p_dev->conf.ConfigIndex = cfg->index;
p_dev->io.BasePort1 = cfg->io.win[0].base;
p_dev->io.NumPorts1 = cfg->io.win[0].len;
if (p_dev->io.BasePort1 == 0)
return -ENODEV;
return pcmcia_request_io(p_dev, &p_dev->io);
}
static int qlogic_config(struct pcmcia_device * link) static int qlogic_config(struct pcmcia_device * link)
{ {
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
tuple_t tuple; int last_ret, last_fn;
cisparse_t parse;
int i, last_ret, last_fn;
unsigned short tuple_data[32];
struct Scsi_Host *host; struct Scsi_Host *host;
DEBUG(0, "qlogic_config(0x%p)\n", link); DEBUG(0, "qlogic_config(0x%p)\n", link);
info->manf_id = link->manf_id; last_ret = pcmcia_loop_config(link, qlogic_config_check, NULL);
if (last_ret) {
tuple.TupleData = (cisdata_t *) tuple_data; cs_error(link, RequestIO, last_ret);
tuple.TupleDataMax = 64; goto failed;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
} }
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@ -262,6 +255,7 @@ static int qlogic_config(struct pcmcia_device * link)
cs_failed: cs_failed:
cs_error(link, last_fn, last_ret); cs_error(link, last_fn, last_ret);
pcmcia_disable_device(link); pcmcia_disable_device(link);
failed:
return -ENODEV; return -ENODEV;
} /* qlogic_config */ } /* qlogic_config */

View File

@ -700,15 +700,26 @@ static struct scsi_host_template sym53c500_driver_template = {
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int SYM53C500_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
p_dev->conf.ConfigIndex = cfg->index;
p_dev->io.BasePort1 = cfg->io.win[0].base;
p_dev->io.NumPorts1 = cfg->io.win[0].len;
if (p_dev->io.BasePort1 == 0)
return -ENODEV;
return pcmcia_request_io(p_dev, &p_dev->io);
}
static int static int
SYM53C500_config(struct pcmcia_device *link) SYM53C500_config(struct pcmcia_device *link)
{ {
struct scsi_info_t *info = link->priv; struct scsi_info_t *info = link->priv;
tuple_t tuple; int last_ret, last_fn;
cisparse_t parse;
int i, last_ret, last_fn;
int irq_level, port_base; int irq_level, port_base;
unsigned short tuple_data[32];
struct Scsi_Host *host; struct Scsi_Host *host;
struct scsi_host_template *tpnt = &sym53c500_driver_template; struct scsi_host_template *tpnt = &sym53c500_driver_template;
struct sym53c500_data *data; struct sym53c500_data *data;
@ -717,27 +728,10 @@ SYM53C500_config(struct pcmcia_device *link)
info->manf_id = link->manf_id; info->manf_id = link->manf_id;
tuple.TupleData = (cisdata_t *)tuple_data; last_ret = pcmcia_loop_config(link, SYM53C500_config_check, NULL);
tuple.TupleDataMax = 64; if (last_ret) {
tuple.TupleOffset = 0; cs_error(link, RequestIO, last_ret);
goto failed;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
pcmcia_parse_tuple(link, &tuple, &parse) != 0)
goto next_entry;
link->conf.ConfigIndex = parse.cftable_entry.index;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
if (link->io.BasePort1 != 0) {
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
break;
}
next_entry:
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
} }
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
@ -831,6 +825,7 @@ err_release:
cs_failed: cs_failed:
cs_error(link, last_fn, last_ret); cs_error(link, last_fn, last_ret);
failed:
SYM53C500_release(link); SYM53C500_release(link);
return -ENODEV; return -ENODEV;
} /* SYM53C500_config */ } /* SYM53C500_config */