提交 84e2d340 编写于 作者: D Dominik Brodowski

pcmcia: use pcmcia_loop_config in misc pcmcia drivers

Use the config loop helper in misc pcmcia drivers.

CC: Harald Welte <laforge@gnumonks.org>
CC: <linux-parport@lists.infradead.org>
CC: Russell King <rmk+kernel@arm.linux.org.uk>
CC: Ed Okerson <eokerson@quicknet.net>
CC: linux-serial@vger.kernel.org
CC: boti@rocketmail.com
CC: linux-usb@vger.kernel.org
Signed-off-by: NDominik Brodowski <linux@dominikbrodowski.net>
上级 b54bf94b
...@@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link) ...@@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
/*==== Interface to PCMCIA Layer =======================================*/ /*==== Interface to PCMCIA Layer =======================================*/
static int cm4000_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
p_dev->conf.ConfigIndex = cfg->index;
if (!cfg->io.nwin)
return -ENODEV;
/* Get the IOaddr */
p_dev->io.BasePort1 = cfg->io.win[0].base;
p_dev->io.NumPorts1 = cfg->io.win[0].len;
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(cfg->io.flags & CISTPL_IO_8BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(cfg->io.flags & CISTPL_IO_16BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
return pcmcia_request_io(p_dev, &p_dev->io);
}
static int cm4000_config(struct pcmcia_device * link, int devno) static int cm4000_config(struct pcmcia_device * link, int devno)
{ {
struct cm4000_dev *dev; struct cm4000_dev *dev;
tuple_t tuple;
cisparse_t parse;
u_char buf[64];
int fail_fn, fail_rc;
int rc;
/* read the config-tuples */ /* read the config-tuples */
tuple.Attributes = 0; if (pcmcia_loop_config(link, cm4000_config_check, NULL))
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
for (rc = pcmcia_get_first_tuple(link, &tuple);
rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
link->conf.ConfigIndex = parse.cftable_entry.index;
if (!parse.cftable_entry.io.nwin)
continue;
/* Get the IOaddr */
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
rc = pcmcia_request_io(link, &link->io);
if (rc == CS_SUCCESS)
break; /* we are done */
}
if (rc != CS_SUCCESS)
goto cs_release; goto cs_release;
link->conf.IntType = 00000002; link->conf.IntType = 00000002;
if ((fail_rc = if (pcmcia_request_configuration(link, &link->conf))
pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
fail_fn = RequestConfiguration;
goto cs_release; goto cs_release;
}
dev = link->priv; dev = link->priv;
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
......
...@@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link) ...@@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return; return;
} }
static int reader_config(struct pcmcia_device *link, int devno) static int cm4040_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{ {
struct reader_dev *dev;
tuple_t tuple;
cisparse_t parse;
u_char buf[64];
int fail_fn, fail_rc;
int rc; int rc;
p_dev->conf.ConfigIndex = cfg->index;
if (!cfg->io.nwin)
return -ENODEV;
tuple.Attributes = 0; /* Get the IOaddr */
tuple.TupleData = buf; p_dev->io.BasePort1 = cfg->io.win[0].base;
tuple.TupleDataMax = sizeof(buf); p_dev->io.NumPorts1 = cfg->io.win[0].len;
tuple.TupleOffset = 0; p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(cfg->io.flags & CISTPL_IO_8BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(cfg->io.flags & CISTPL_IO_16BIT))
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
rc = pcmcia_request_io(p_dev, &p_dev->io);
dev_printk(KERN_INFO, &handle_to_dev(p_dev),
"pcmcia_request_io returned 0x%x\n", rc);
return rc;
}
static int reader_config(struct pcmcia_device *link, int devno)
{
struct reader_dev *dev;
int fail_rc;
link->io.BasePort2 = 0; link->io.BasePort2 = 0;
link->io.NumPorts2 = 0; link->io.NumPorts2 = 0;
link->io.Attributes2 = 0; link->io.Attributes2 = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
for (rc = pcmcia_get_first_tuple(link, &tuple); if (pcmcia_loop_config(link, cm4040_config_check, NULL))
rc == CS_SUCCESS;
rc = pcmcia_get_next_tuple(link, &tuple)) {
rc = pcmcia_get_tuple_data(link, &tuple);
if (rc != CS_SUCCESS)
continue;
rc = pcmcia_parse_tuple(link, &tuple, &parse);
if (rc != CS_SUCCESS)
continue;
link->conf.ConfigIndex = parse.cftable_entry.index;
if (!parse.cftable_entry.io.nwin)
continue;
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = parse.cftable_entry.io.flags
& CISTPL_IO_LINES_MASK;
rc = pcmcia_request_io(link, &link->io);
dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
if (rc == CS_SUCCESS)
break;
else
dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_io failed 0x%x\n", rc);
}
if (rc != CS_SUCCESS)
goto cs_release; goto cs_release;
link->conf.IntType = 00000002; link->conf.IntType = 00000002;
if ((fail_rc = pcmcia_request_configuration(link,&link->conf)) if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
!=CS_SUCCESS) { !=CS_SUCCESS) {
fail_fn = RequestConfiguration;
dev_printk(KERN_INFO, &handle_to_dev(link), dev_printk(KERN_INFO, &handle_to_dev(link),
"pcmcia_request_configuration failed 0x%x\n", "pcmcia_request_configuration failed 0x%x\n",
fail_rc); fail_rc);
......
...@@ -149,52 +149,49 @@ static void parport_detach(struct pcmcia_device *link) ...@@ -149,52 +149,49 @@ static void parport_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 parport_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
cistpl_cftable_entry_t *dflt = priv_data;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->conf.ConfigIndex = cfg->index;
if (epp_mode)
p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
p_dev->io.BasePort1 = io->win[0].base;
p_dev->io.NumPorts1 = io->win[0].len;
p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
if (io->nwin == 2) {
p_dev->io.BasePort2 = io->win[1].base;
p_dev->io.NumPorts2 = io->win[1].len;
}
if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
goto next_entry;
return 0;
}
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
*dflt = *cfg;
return -ENODEV;
}
static int parport_config(struct pcmcia_device *link) static int parport_config(struct pcmcia_device *link)
{ {
parport_info_t *info = link->priv; parport_info_t *info = link->priv;
tuple_t tuple;
u_short buf[128];
cisparse_t parse;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t dflt = { 0 };
struct parport *p; struct parport *p;
int last_ret, last_fn; int last_ret, last_fn;
DEBUG(0, "parport_config(0x%p)\n", link); DEBUG(0, "parport_config(0x%p)\n", link);
tuple.TupleData = (cisdata_t *)buf; last_ret = pcmcia_loop_config(link, parport_config_check, &dflt);
tuple.TupleOffset = 0; tuple.TupleDataMax = 255; if (last_ret) {
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; cs_error(link, RequestIO, last_ret);
tuple.Attributes = 0; goto failed;
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;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->conf.ConfigIndex = cfg->index;
if (epp_mode)
link->conf.ConfigIndex |= FORCE_EPP_MODE;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
if (io->nwin == 2) {
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
}
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
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));
......
...@@ -439,43 +439,55 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) ...@@ -439,43 +439,55 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
return pcmcia_parse_tuple(handle, tuple, parse); return pcmcia_parse_tuple(handle, tuple, parse);
} }
static int /*====================================================================*/
next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
static int simple_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
void *priv_data)
{ {
int i; static const int size_table[2] = { 8, 16 };
i = pcmcia_get_next_tuple(handle, tuple); int *try = priv_data;
if (i != CS_SUCCESS)
return CS_NO_MORE_ITEMS; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
i = pcmcia_get_tuple_data(handle, tuple); p_dev->conf.Vpp =
if (i != CS_SUCCESS) cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
return i;
return pcmcia_parse_tuple(handle, tuple, parse); if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
&& (cf->io.win[0].base != 0)) {
p_dev->conf.ConfigIndex = cf->index;
p_dev->io.BasePort1 = cf->io.win[0].base;
p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
if (!pcmcia_request_io(p_dev, &p_dev->io))
return 0;
}
return -EINVAL;
} }
/*====================================================================*/ static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
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)) {
p_dev->conf.ConfigIndex = cf->index;
for (j = 0; j < 5; j++) {
p_dev->io.BasePort1 = base[j];
p_dev->io.IOAddrLines = base[j] ? 16 : 3;
if (!pcmcia_request_io(p_dev, &p_dev->io))
return 0;
}
}
return -ENODEV;
}
static int simple_config(struct pcmcia_device *link) static int simple_config(struct pcmcia_device *link)
{ {
static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
static const int size_table[2] = { 8, 16 };
struct serial_info *info = link->priv; struct serial_info *info = link->priv;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple;
u_char *buf;
cisparse_t *parse;
cistpl_cftable_entry_t *cf;
config_info_t config; config_info_t config;
int i, j, try; int i, try;
int s;
cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
if (!cfg_mem)
return -1;
tuple = &cfg_mem->tuple;
parse = &cfg_mem->parse;
cf = &parse->cftable_entry;
buf = cfg_mem->buf;
/* If the card is already configured, look up the port and irq */ /* If the card is already configured, look up the port and irq */
i = pcmcia_get_configuration_info(link, &config); i = pcmcia_get_configuration_info(link, &config);
...@@ -490,70 +502,28 @@ static int simple_config(struct pcmcia_device *link) ...@@ -490,70 +502,28 @@ static int simple_config(struct pcmcia_device *link)
info->slave = 1; info->slave = 1;
} }
if (info->slave) { if (info->slave) {
kfree(cfg_mem);
return setup_serial(link, info, port, config.AssignedIRQ); return setup_serial(link, info, port, config.AssignedIRQ);
} }
} }
/* First pass: look for a config entry that looks normal. */ /* First pass: look for a config entry that looks normal.
tuple->TupleData = (cisdata_t *) buf; * Two tries: without IO aliases, then with aliases */
tuple->TupleOffset = 0; for (try = 0; try < 4; try++)
tuple->TupleDataMax = 255; if (!pcmcia_loop_config(link, simple_config_check, &try))
tuple->Attributes = 0; goto found_port;
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* Two tries: without IO aliases, then with aliases */
for (s = 0; s < 2; s++) {
for (try = 0; try < 2; try++) {
i = first_tuple(link, tuple, parse);
while (i != CS_NO_MORE_ITEMS) {
if (i != CS_SUCCESS)
goto next_entry;
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
link->conf.Vpp =
cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
(cf->io.win[0].base != 0)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines = (try == 0) ?
16 : cf->io.flags & CISTPL_IO_LINES_MASK;
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
next_entry:
i = next_tuple(link, tuple, parse);
}
}
}
/* Second pass: try to find an entry that isn't picky about /* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port its base address, then try to grab any standard serial port
address, and finally try to get any free port. */ address, and finally try to get any free port. */
i = first_tuple(link, tuple, parse); if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
while (i != CS_NO_MORE_ITEMS) { goto found_port;
if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
link->conf.ConfigIndex = cf->index;
for (j = 0; j < 5; j++) {
link->io.BasePort1 = base[j];
link->io.IOAddrLines = base[j] ? 16 : 3;
i = pcmcia_request_io(link, &link->io);
if (i == CS_SUCCESS)
goto found_port;
}
}
i = next_tuple(link, tuple, parse);
}
found_port: printk(KERN_NOTICE
if (i != CS_SUCCESS) { "serial_cs: no usable port range found, giving up\n");
printk(KERN_NOTICE cs_error(link, RequestIO, i);
"serial_cs: no usable port range found, giving up\n"); return -1;
cs_error(link, RequestIO, i);
kfree(cfg_mem);
return -1;
}
found_port:
i = pcmcia_request_irq(link, &link->irq); i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) { if (i != CS_SUCCESS) {
cs_error(link, RequestIRQ, i); cs_error(link, RequestIRQ, i);
...@@ -571,86 +541,72 @@ static int simple_config(struct pcmcia_device *link) ...@@ -571,86 +541,72 @@ static int simple_config(struct pcmcia_device *link)
i = pcmcia_request_configuration(link, &link->conf); i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) { if (i != CS_SUCCESS) {
cs_error(link, RequestConfiguration, i); cs_error(link, RequestConfiguration, i);
kfree(cfg_mem);
return -1; return -1;
} }
kfree(cfg_mem);
return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
} }
static int multi_config(struct pcmcia_device * link) static int multi_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cf,
void *priv_data)
{ {
struct serial_info *info = link->priv; int *base2 = priv_data;
struct serial_cfg_mem *cfg_mem;
tuple_t *tuple; /* The quad port cards have bad CIS's, so just look for a
u_char *buf; window larger than 8 ports and assume it will be right */
cisparse_t *parse; if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
cistpl_cftable_entry_t *cf; p_dev->conf.ConfigIndex = cf->index;
int i, rc, base2 = 0; p_dev->io.BasePort1 = cf->io.win[0].base;
p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
if (!pcmcia_request_io(p_dev, &p_dev->io)) {
*base2 = p_dev->io.BasePort1 + 8;
return 0;
}
}
return -ENODEV;
}
cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
if (!cfg_mem) cistpl_cftable_entry_t *cf,
return -1; void *priv_data)
tuple = &cfg_mem->tuple; {
parse = &cfg_mem->parse; int *base2 = priv_data;
cf = &parse->cftable_entry;
buf = cfg_mem->buf; if (cf->io.nwin == 2) {
p_dev->conf.ConfigIndex = cf->index;
p_dev->io.BasePort1 = cf->io.win[0].base;
p_dev->io.BasePort2 = cf->io.win[1].base;
p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
if (!pcmcia_request_io(p_dev, &p_dev->io)) {
*base2 = p_dev->io.BasePort2;
return 0;
}
}
return -ENODEV;
}
tuple->TupleData = (cisdata_t *) buf; static int multi_config(struct pcmcia_device *link)
tuple->TupleOffset = 0; {
tuple->TupleDataMax = 255; struct serial_info *info = link->priv;
tuple->Attributes = 0; int i, base2 = 0;
tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
/* First, look for a generic full-sized window */ /* First, look for a generic full-sized window */
link->io.NumPorts1 = info->multi * 8; link->io.NumPorts1 = info->multi * 8;
i = first_tuple(link, tuple, parse); if (pcmcia_loop_config(link, multi_config_check, &base2)) {
while (i != CS_NO_MORE_ITEMS) { /* If that didn't work, look for two windows */
/* 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 ((i == CS_SUCCESS) && (cf->io.nwin == 1) &&
(cf->io.win[0].len > 8)) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort1 + 8;
if (i == CS_SUCCESS)
break;
}
i = next_tuple(link, tuple, parse);
}
/* If that didn't work, look for two windows */
if (i != CS_SUCCESS) {
link->io.NumPorts1 = link->io.NumPorts2 = 8; link->io.NumPorts1 = link->io.NumPorts2 = 8;
info->multi = 2; info->multi = 2;
i = first_tuple(link, tuple, parse); if (pcmcia_loop_config(link, multi_config_check_notpicky,
while (i != CS_NO_MORE_ITEMS) { &base2)) {
if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { printk(KERN_NOTICE "serial_cs: no usable port range"
link->conf.ConfigIndex = cf->index; "found, giving up\n");
link->io.BasePort1 = cf->io.win[0].base; return -ENODEV;
link->io.BasePort2 = cf->io.win[1].base;
link->io.IOAddrLines =
cf->io.flags & CISTPL_IO_LINES_MASK;
i = pcmcia_request_io(link, &link->io);
base2 = link->io.BasePort2;
if (i == CS_SUCCESS)
break;
}
i = next_tuple(link, tuple, parse);
} }
} }
if (i != CS_SUCCESS) {
cs_error(link, RequestIO, i);
rc = -1;
goto free_cfg_mem;
}
i = pcmcia_request_irq(link, &link->irq); i = pcmcia_request_irq(link, &link->irq);
if (i != CS_SUCCESS) { if (i != CS_SUCCESS) {
/* FIXME: comment does not fit, error handling does not fit */
printk(KERN_NOTICE printk(KERN_NOTICE
"serial_cs: no usable port range found, giving up\n"); "serial_cs: no usable port range found, giving up\n");
cs_error(link, RequestIRQ, i); cs_error(link, RequestIRQ, i);
...@@ -666,8 +622,7 @@ static int multi_config(struct pcmcia_device * link) ...@@ -666,8 +622,7 @@ static int multi_config(struct pcmcia_device * link)
i = pcmcia_request_configuration(link, &link->conf); i = pcmcia_request_configuration(link, &link->conf);
if (i != CS_SUCCESS) { if (i != CS_SUCCESS) {
cs_error(link, RequestConfiguration, i); cs_error(link, RequestConfiguration, i);
rc = -1; return -ENODEV;
goto free_cfg_mem;
} }
/* The Oxford Semiconductor OXCF950 cards are in fact single-port: /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
...@@ -678,7 +633,8 @@ static int multi_config(struct pcmcia_device * link) ...@@ -678,7 +633,8 @@ static int multi_config(struct pcmcia_device * link)
info->prodid == PRODID_POSSIO_GCC)) { info->prodid == PRODID_POSSIO_GCC)) {
int err; int err;
if (cf->index == 1 || cf->index == 3) { if (link->conf.ConfigIndex == 1 ||
link->conf.ConfigIndex == 3) {
err = setup_serial(link, info, base2, err = setup_serial(link, info, base2,
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
base2 = link->io.BasePort1; base2 = link->io.BasePort1;
...@@ -695,18 +651,14 @@ static int multi_config(struct pcmcia_device * link) ...@@ -695,18 +651,14 @@ static int multi_config(struct pcmcia_device * link)
if (info->quirk && info->quirk->wakeup) if (info->quirk && info->quirk->wakeup)
info->quirk->wakeup(link); info->quirk->wakeup(link);
rc = 0; return 0;
goto free_cfg_mem;
} }
setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
for (i = 0; i < info->multi - 1; i++) for (i = 0; i < info->multi - 1; i++)
setup_serial(link, info, base2 + (8 * i), setup_serial(link, info, base2 + (8 * i),
link->irq.AssignedIRQ); link->irq.AssignedIRQ);
rc = 0; return 0;
free_cfg_mem:
kfree(cfg_mem);
return rc;
} }
/*====================================================================== /*======================================================================
......
...@@ -124,65 +124,57 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) ...@@ -124,65 +124,57 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
return; return;
} }
static int ixj_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
cistpl_cftable_entry_t *dflt = priv_data;
if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
p_dev->conf.ConfigIndex = cfg->index;
p_dev->io.BasePort1 = io->win[0].base;
p_dev->io.NumPorts1 = io->win[0].len;
if (io->nwin == 2) {
p_dev->io.BasePort2 = io->win[1].base;
p_dev->io.NumPorts2 = io->win[1].len;
}
if (pcmcia_request_io(p_dev, &p_dev->io)) {
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
*dflt = *cfg;
} else
return 0;
}
return -ENODEV;
}
static int ixj_config(struct pcmcia_device * link) static int ixj_config(struct pcmcia_device * link)
{ {
IXJ *j; IXJ *j;
ixj_info_t *info; ixj_info_t *info;
tuple_t tuple; cistpl_cftable_entry_t dflt = { 0 };
u_short buf[128];
cisparse_t parse;
cistpl_cftable_entry_t *cfg = &parse.cftable_entry;
cistpl_cftable_entry_t dflt =
{
0
};
int last_ret, last_fn;
info = link->priv; info = link->priv;
DEBUG(0, "ixj_config(0x%p)\n", link); DEBUG(0, "ixj_config(0x%p)\n", link);
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
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;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->conf.ConfigIndex = cfg->index;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
if (io->nwin == 2) {
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
/* If we've got this far, we're done */
break;
}
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
}
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (pcmcia_loop_config(link, ixj_config_check, &dflt))
goto cs_failed;
if (pcmcia_request_configuration(link, &link->conf))
goto cs_failed;
/* /*
* Register the card with the core. * Register the card with the core.
*/ */
j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10); j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10);
info->ndev = 1; info->ndev = 1;
info->node.major = PHONE_MAJOR; info->node.major = PHONE_MAJOR;
link->dev_node = &info->node; link->dev_node = &info->node;
ixj_get_serial(link, j); ixj_get_serial(link, j);
return 0; return 0;
cs_failed: cs_failed:
cs_error(link, last_fn, last_ret);
ixj_cs_release(link); ixj_cs_release(link);
return -ENODEV; return -ENODEV;
} }
......
...@@ -155,88 +155,84 @@ static void sl811_cs_release(struct pcmcia_device * link) ...@@ -155,88 +155,84 @@ static void sl811_cs_release(struct pcmcia_device * link)
platform_device_unregister(&platform_dev); platform_device_unregister(&platform_dev);
} }
struct sl811_css_cfg {
cistpl_cftable_entry_t dflt;
config_info_t conf;
};
static int sl811_cs_config_check(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg,
void *priv_data)
{
struct sl811_css_cfg *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;
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 !=
cfg_mem->conf.Vcc)
return -ENODEV;
} else if (cfg_mem->dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM]/10000
!= cfg_mem->conf.Vcc)
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;
/* we need 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_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;
return pcmcia_request_io(p_dev, &p_dev->io);
}
pcmcia_disable_device(p_dev);
return -ENODEV;
}
static int sl811_cs_config(struct pcmcia_device *link) static int sl811_cs_config(struct pcmcia_device *link)
{ {
struct device *parent = &handle_to_dev(link); struct device *parent = &handle_to_dev(link);
local_info_t *dev = link->priv; local_info_t *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
int last_fn, last_ret; int last_fn, last_ret;
u_char buf[64]; struct sl811_css_cfg *cfg_mem;
config_info_t conf;
cistpl_cftable_entry_t dflt = { 0 };
DBG(0, "sl811_cs_config(0x%p)\n", link); DBG(0, "sl811_cs_config(0x%p)\n", link);
cfg_mem = kzalloc(sizeof(struct sl811_css_cfg), GFP_KERNEL);
if (!cfg_mem)
return -ENOMEM;
/* Look up the current Vcc */ /* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo, CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(link, &conf)); pcmcia_get_configuration_info(link, &cfg_mem->conf));
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
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) if (pcmcia_loop_config(link, sl811_cs_config_check, cfg_mem))
goto next_entry; return -ENODEV;
link->conf.ConfigIndex = cfg->index;
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
!= conf.Vcc)
goto next_entry;
} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
!= conf.Vcc)
goto next_entry;
}
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
link->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
/* we need an interrupt */
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
link->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
link->io.BasePort1 = io->win[0].base;
link->io.NumPorts1 = io->win[0].len;
if (pcmcia_request_io(link, &link->io) != 0)
goto next_entry;
}
break;
next_entry:
pcmcia_disable_device(link);
last_ret = pcmcia_get_next_tuple(link, &tuple);
}
/* require an IRQ and two registers */ /* require an IRQ and two registers */
if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
...@@ -269,8 +265,10 @@ static int sl811_cs_config(struct pcmcia_device *link) ...@@ -269,8 +265,10 @@ static int sl811_cs_config(struct pcmcia_device *link)
printk("sl811_cs_config failed\n"); printk("sl811_cs_config failed\n");
cs_error(link, last_fn, last_ret); cs_error(link, last_fn, last_ret);
sl811_cs_release(link); sl811_cs_release(link);
kfree(cfg_mem);
return -ENODEV; return -ENODEV;
} }
kfree(cfg_mem);
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册