|
@@ -424,41 +424,45 @@ static int pfc_config(struct pcmcia_device *p_dev)
|
|
return -ENODEV;
|
|
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 };
|
|
static const int size_table[2] = { 8, 16 };
|
|
int *try = priv_data;
|
|
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,
|
|
static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
|
|
- cistpl_cftable_entry_t *cf,
|
|
|
|
- cistpl_cftable_entry_t *dflt,
|
|
|
|
void *priv_data)
|
|
void *priv_data)
|
|
{
|
|
{
|
|
static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
|
|
static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
|
|
int j;
|
|
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;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
@@ -468,12 +472,9 @@ static int simple_config(struct pcmcia_device *link)
|
|
struct serial_info *info = link->priv;
|
|
struct serial_info *info = link->priv;
|
|
int i = -ENODEV, try;
|
|
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.
|
|
/* First pass: look for a config entry that looks normal.
|
|
* Two tries: without IO aliases, then with aliases */
|
|
* 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++)
|
|
for (try = 0; try < 4; try++)
|
|
if (!pcmcia_loop_config(link, simple_config_check, &try))
|
|
if (!pcmcia_loop_config(link, simple_config_check, &try))
|
|
goto found_port;
|
|
goto found_port;
|
|
@@ -503,43 +504,44 @@ found_port:
|
|
return setup_serial(link, info, link->resource[0]->start, link->irq);
|
|
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
|
|
/* The quad port cards have bad CIS's, so just look for a
|
|
window larger than 8 ports and assume it will be right */
|
|
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,
|
|
static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
|
|
- cistpl_cftable_entry_t *cf,
|
|
|
|
- cistpl_cftable_entry_t *dflt,
|
|
|
|
void *priv_data)
|
|
void *priv_data)
|
|
{
|
|
{
|
|
int *base2 = 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)
|
|
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;
|
|
struct serial_info *info = link->priv;
|
|
int i, base2 = 0;
|
|
int i, base2 = 0;
|
|
|
|
|
|
|
|
+ link->config_flags |= CONF_AUTO_SET_IO;
|
|
/* First, look for a generic full-sized window */
|
|
/* 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 */
|
|
/* If that didn't work, look for two windows */
|
|
- link->resource[0]->end = link->resource[1]->end = 8;
|
|
|
|
info->multi = 2;
|
|
info->multi = 2;
|
|
if (pcmcia_loop_config(link, multi_config_check_notpicky,
|
|
if (pcmcia_loop_config(link, multi_config_check_notpicky,
|
|
&base2)) {
|
|
&base2)) {
|
|
@@ -587,7 +589,7 @@ static int multi_config(struct pcmcia_device *link)
|
|
link->config_index == 3) {
|
|
link->config_index == 3) {
|
|
err = setup_serial(link, info, base2,
|
|
err = setup_serial(link, info, base2,
|
|
link->irq);
|
|
link->irq);
|
|
- base2 = link->resource[0]->start;;
|
|
|
|
|
|
+ base2 = link->resource[0]->start;
|
|
} else {
|
|
} else {
|
|
err = setup_serial(link, info, link->resource[0]->start,
|
|
err = setup_serial(link, info, link->resource[0]->start,
|
|
link->irq);
|
|
link->irq);
|
|
@@ -611,18 +613,18 @@ static int multi_config(struct pcmcia_device *link)
|
|
return 0;
|
|
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;
|
|
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;
|
|
info->multi = 2;
|
|
|
|
|
|
return 0; /* break */
|
|
return 0; /* break */
|