diff options
| -rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 73 | ||||
| -rw-r--r-- | drivers/char/pcmcia/cm4040_cs.c | 76 | ||||
| -rw-r--r-- | drivers/parport/parport_cs.c | 73 | ||||
| -rw-r--r-- | drivers/serial/serial_cs.c | 262 | ||||
| -rw-r--r-- | drivers/telephony/ixj_pcmcia.c | 76 | ||||
| -rw-r--r-- | drivers/usb/host/sl811_cs.c | 140 |
6 files changed, 299 insertions, 401 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index f070ae7bd91a..47adec480bd1 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
| @@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link) | |||
| 1759 | 1759 | ||
| 1760 | /*==== Interface to PCMCIA Layer =======================================*/ | 1760 | /*==== Interface to PCMCIA Layer =======================================*/ |
| 1761 | 1761 | ||
| 1762 | static int cm4000_config_check(struct pcmcia_device *p_dev, | ||
| 1763 | cistpl_cftable_entry_t *cfg, | ||
| 1764 | void *priv_data) | ||
| 1765 | { | ||
| 1766 | p_dev->conf.ConfigIndex = cfg->index; | ||
| 1767 | |||
| 1768 | if (!cfg->io.nwin) | ||
| 1769 | return -ENODEV; | ||
| 1770 | |||
| 1771 | /* Get the IOaddr */ | ||
| 1772 | p_dev->io.BasePort1 = cfg->io.win[0].base; | ||
| 1773 | p_dev->io.NumPorts1 = cfg->io.win[0].len; | ||
| 1774 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
| 1775 | if (!(cfg->io.flags & CISTPL_IO_8BIT)) | ||
| 1776 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
| 1777 | if (!(cfg->io.flags & CISTPL_IO_16BIT)) | ||
| 1778 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 1779 | p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
| 1780 | |||
| 1781 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
| 1782 | } | ||
| 1783 | |||
| 1762 | static int cm4000_config(struct pcmcia_device * link, int devno) | 1784 | static int cm4000_config(struct pcmcia_device * link, int devno) |
| 1763 | { | 1785 | { |
| 1764 | struct cm4000_dev *dev; | 1786 | struct cm4000_dev *dev; |
| 1765 | tuple_t tuple; | ||
| 1766 | cisparse_t parse; | ||
| 1767 | u_char buf[64]; | ||
| 1768 | int fail_fn, fail_rc; | ||
| 1769 | int rc; | ||
| 1770 | 1787 | ||
| 1771 | /* read the config-tuples */ | 1788 | /* read the config-tuples */ |
| 1772 | tuple.Attributes = 0; | 1789 | if (pcmcia_loop_config(link, cm4000_config_check, NULL)) |
| 1773 | tuple.TupleData = buf; | ||
| 1774 | tuple.TupleDataMax = sizeof(buf); | ||
| 1775 | tuple.TupleOffset = 0; | ||
| 1776 | |||
| 1777 | link->io.BasePort2 = 0; | ||
| 1778 | link->io.NumPorts2 = 0; | ||
| 1779 | link->io.Attributes2 = 0; | ||
| 1780 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
| 1781 | for (rc = pcmcia_get_first_tuple(link, &tuple); | ||
| 1782 | rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) { | ||
| 1783 | |||
| 1784 | rc = pcmcia_get_tuple_data(link, &tuple); | ||
| 1785 | if (rc != CS_SUCCESS) | ||
| 1786 | continue; | ||
| 1787 | rc = pcmcia_parse_tuple(link, &tuple, &parse); | ||
| 1788 | if (rc != CS_SUCCESS) | ||
| 1789 | continue; | ||
| 1790 | |||
| 1791 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
| 1792 | |||
| 1793 | if (!parse.cftable_entry.io.nwin) | ||
| 1794 | continue; | ||
| 1795 | |||
| 1796 | /* Get the IOaddr */ | ||
| 1797 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
| 1798 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
| 1799 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
| 1800 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
| 1801 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
| 1802 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
| 1803 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 1804 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
| 1805 | & CISTPL_IO_LINES_MASK; | ||
| 1806 | |||
| 1807 | rc = pcmcia_request_io(link, &link->io); | ||
| 1808 | if (rc == CS_SUCCESS) | ||
| 1809 | break; /* we are done */ | ||
| 1810 | } | ||
| 1811 | if (rc != CS_SUCCESS) | ||
| 1812 | goto cs_release; | 1790 | goto cs_release; |
| 1813 | 1791 | ||
| 1814 | link->conf.IntType = 00000002; | 1792 | link->conf.IntType = 00000002; |
| 1815 | 1793 | ||
| 1816 | if ((fail_rc = | 1794 | if (pcmcia_request_configuration(link, &link->conf)) |
| 1817 | pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) { | ||
| 1818 | fail_fn = RequestConfiguration; | ||
| 1819 | goto cs_release; | 1795 | goto cs_release; |
| 1820 | } | ||
| 1821 | 1796 | ||
| 1822 | dev = link->priv; | 1797 | dev = link->priv; |
| 1823 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); | 1798 | sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 0b5934bef7a4..e0f5d8c9b266 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
| @@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link) | |||
| 526 | return; | 526 | return; |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | static int reader_config(struct pcmcia_device *link, int devno) | 529 | static int cm4040_config_check(struct pcmcia_device *p_dev, |
| 530 | cistpl_cftable_entry_t *cfg, | ||
| 531 | void *priv_data) | ||
| 530 | { | 532 | { |
| 531 | struct reader_dev *dev; | ||
| 532 | tuple_t tuple; | ||
| 533 | cisparse_t parse; | ||
| 534 | u_char buf[64]; | ||
| 535 | int fail_fn, fail_rc; | ||
| 536 | int rc; | 533 | int rc; |
| 534 | p_dev->conf.ConfigIndex = cfg->index; | ||
| 535 | |||
| 536 | if (!cfg->io.nwin) | ||
| 537 | return -ENODEV; | ||
| 537 | 538 | ||
| 538 | tuple.Attributes = 0; | 539 | /* Get the IOaddr */ |
| 539 | tuple.TupleData = buf; | 540 | p_dev->io.BasePort1 = cfg->io.win[0].base; |
| 540 | tuple.TupleDataMax = sizeof(buf); | 541 | p_dev->io.NumPorts1 = cfg->io.win[0].len; |
| 541 | tuple.TupleOffset = 0; | 542 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
| 543 | if (!(cfg->io.flags & CISTPL_IO_8BIT)) | ||
| 544 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
| 545 | if (!(cfg->io.flags & CISTPL_IO_16BIT)) | ||
| 546 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 547 | p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; | ||
| 548 | |||
| 549 | rc = pcmcia_request_io(p_dev, &p_dev->io); | ||
| 550 | dev_printk(KERN_INFO, &handle_to_dev(p_dev), | ||
| 551 | "pcmcia_request_io returned 0x%x\n", rc); | ||
| 552 | return rc; | ||
| 553 | } | ||
| 554 | |||
| 555 | |||
| 556 | static int reader_config(struct pcmcia_device *link, int devno) | ||
| 557 | { | ||
| 558 | struct reader_dev *dev; | ||
| 559 | int fail_rc; | ||
| 542 | 560 | ||
| 543 | link->io.BasePort2 = 0; | 561 | link->io.BasePort2 = 0; |
| 544 | link->io.NumPorts2 = 0; | 562 | link->io.NumPorts2 = 0; |
| 545 | link->io.Attributes2 = 0; | 563 | link->io.Attributes2 = 0; |
| 546 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 564 | |
| 547 | for (rc = pcmcia_get_first_tuple(link, &tuple); | 565 | if (pcmcia_loop_config(link, cm4040_config_check, NULL)) |
| 548 | rc == CS_SUCCESS; | ||
| 549 | rc = pcmcia_get_next_tuple(link, &tuple)) { | ||
| 550 | rc = pcmcia_get_tuple_data(link, &tuple); | ||
| 551 | if (rc != CS_SUCCESS) | ||
| 552 | continue; | ||
| 553 | rc = pcmcia_parse_tuple(link, &tuple, &parse); | ||
| 554 | if (rc != CS_SUCCESS) | ||
| 555 | continue; | ||
| 556 | |||
| 557 | link->conf.ConfigIndex = parse.cftable_entry.index; | ||
| 558 | |||
| 559 | if (!parse.cftable_entry.io.nwin) | ||
| 560 | continue; | ||
| 561 | |||
| 562 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | ||
| 563 | link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; | ||
| 564 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
| 565 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT)) | ||
| 566 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | ||
| 567 | if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT)) | ||
| 568 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 569 | link->io.IOAddrLines = parse.cftable_entry.io.flags | ||
| 570 | & CISTPL_IO_LINES_MASK; | ||
| 571 | rc = pcmcia_request_io(link, &link->io); | ||
| 572 | |||
| 573 | dev_printk(KERN_INFO, &handle_to_dev(link), "foo"); | ||
| 574 | if (rc == CS_SUCCESS) | ||
| 575 | break; | ||
| 576 | else | ||
| 577 | dev_printk(KERN_INFO, &handle_to_dev(link), | ||
| 578 | "pcmcia_request_io failed 0x%x\n", rc); | ||
| 579 | } | ||
| 580 | if (rc != CS_SUCCESS) | ||
| 581 | goto cs_release; | 566 | goto cs_release; |
| 582 | 567 | ||
| 583 | link->conf.IntType = 00000002; | 568 | link->conf.IntType = 00000002; |
| 584 | 569 | ||
| 585 | if ((fail_rc = pcmcia_request_configuration(link,&link->conf)) | 570 | if ((fail_rc = pcmcia_request_configuration(link,&link->conf)) |
| 586 | !=CS_SUCCESS) { | 571 | !=CS_SUCCESS) { |
| 587 | fail_fn = RequestConfiguration; | ||
| 588 | dev_printk(KERN_INFO, &handle_to_dev(link), | 572 | dev_printk(KERN_INFO, &handle_to_dev(link), |
| 589 | "pcmcia_request_configuration failed 0x%x\n", | 573 | "pcmcia_request_configuration failed 0x%x\n", |
| 590 | fail_rc); | 574 | fail_rc); |
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 00e1d9620f7c..636231739f4b 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
| @@ -149,52 +149,49 @@ static void parport_detach(struct pcmcia_device *link) | |||
| 149 | #define CS_CHECK(fn, ret) \ | 149 | #define CS_CHECK(fn, ret) \ |
| 150 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 150 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
| 151 | 151 | ||
| 152 | static int parport_config_check(struct pcmcia_device *p_dev, | ||
| 153 | cistpl_cftable_entry_t *cfg, | ||
| 154 | void *priv_data) | ||
| 155 | { | ||
| 156 | cistpl_cftable_entry_t *dflt = priv_data; | ||
| 157 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
| 158 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
| 159 | p_dev->conf.ConfigIndex = cfg->index; | ||
| 160 | if (epp_mode) | ||
| 161 | p_dev->conf.ConfigIndex |= FORCE_EPP_MODE; | ||
| 162 | p_dev->io.BasePort1 = io->win[0].base; | ||
| 163 | p_dev->io.NumPorts1 = io->win[0].len; | ||
| 164 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
| 165 | if (io->nwin == 2) { | ||
| 166 | p_dev->io.BasePort2 = io->win[1].base; | ||
| 167 | p_dev->io.NumPorts2 = io->win[1].len; | ||
| 168 | } | ||
| 169 | if (pcmcia_request_io(p_dev, &p_dev->io) != 0) | ||
| 170 | goto next_entry; | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | next_entry: | ||
| 175 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
| 176 | *dflt = *cfg; | ||
| 177 | return -ENODEV; | ||
| 178 | } | ||
| 179 | |||
| 152 | static int parport_config(struct pcmcia_device *link) | 180 | static int parport_config(struct pcmcia_device *link) |
| 153 | { | 181 | { |
| 154 | parport_info_t *info = link->priv; | 182 | parport_info_t *info = link->priv; |
| 155 | tuple_t tuple; | ||
| 156 | u_short buf[128]; | ||
| 157 | cisparse_t parse; | ||
| 158 | cistpl_cftable_entry_t *cfg = &parse.cftable_entry; | ||
| 159 | cistpl_cftable_entry_t dflt = { 0 }; | 183 | cistpl_cftable_entry_t dflt = { 0 }; |
| 160 | struct parport *p; | 184 | struct parport *p; |
| 161 | int last_ret, last_fn; | 185 | int last_ret, last_fn; |
| 162 | 186 | ||
| 163 | DEBUG(0, "parport_config(0x%p)\n", link); | 187 | DEBUG(0, "parport_config(0x%p)\n", link); |
| 164 | 188 | ||
| 165 | tuple.TupleData = (cisdata_t *)buf; | 189 | last_ret = pcmcia_loop_config(link, parport_config_check, &dflt); |
| 166 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 190 | if (last_ret) { |
| 167 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 191 | cs_error(link, RequestIO, last_ret); |
| 168 | tuple.Attributes = 0; | 192 | goto failed; |
| 169 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
| 170 | while (1) { | ||
| 171 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || | ||
| 172 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) | ||
| 173 | goto next_entry; | ||
| 174 | |||
| 175 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
| 176 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
| 177 | link->conf.ConfigIndex = cfg->index; | ||
| 178 | if (epp_mode) | ||
| 179 | link->conf.ConfigIndex |= FORCE_EPP_MODE; | ||
| 180 | link->io.BasePort1 = io->win[0].base; | ||
| 181 | link->io.NumPorts1 = io->win[0].len; | ||
| 182 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
| 183 | if (io->nwin == 2) { | ||
| 184 | link->io.BasePort2 = io->win[1].base; | ||
| 185 | link->io.NumPorts2 = io->win[1].len; | ||
| 186 | } | ||
| 187 | if (pcmcia_request_io(link, &link->io) != 0) | ||
| 188 | goto next_entry; | ||
| 189 | /* If we've got this far, we're done */ | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | |||
| 193 | next_entry: | ||
| 194 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | ||
| 195 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); | ||
| 196 | } | 193 | } |
| 197 | 194 | ||
| 198 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 195 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
| 199 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 196 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
| 200 | 197 | ||
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 164d2a42eb59..ac60cd288418 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
| @@ -439,43 +439,55 @@ first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) | |||
| 439 | return pcmcia_parse_tuple(handle, tuple, parse); | 439 | return pcmcia_parse_tuple(handle, tuple, parse); |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | static int | 442 | /*====================================================================*/ |
| 443 | next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) | 443 | |
| 444 | static int simple_config_check(struct pcmcia_device *p_dev, | ||
| 445 | cistpl_cftable_entry_t *cf, | ||
| 446 | void *priv_data) | ||
| 444 | { | 447 | { |
| 445 | int i; | 448 | static const int size_table[2] = { 8, 16 }; |
| 446 | i = pcmcia_get_next_tuple(handle, tuple); | 449 | int *try = priv_data; |
| 447 | if (i != CS_SUCCESS) | 450 | |
| 448 | return CS_NO_MORE_ITEMS; | 451 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
| 449 | i = pcmcia_get_tuple_data(handle, tuple); | 452 | p_dev->conf.Vpp = |
| 450 | if (i != CS_SUCCESS) | 453 | cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
| 451 | return i; | 454 | |
| 452 | return pcmcia_parse_tuple(handle, tuple, parse); | 455 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)]) |
| 456 | && (cf->io.win[0].base != 0)) { | ||
| 457 | p_dev->conf.ConfigIndex = cf->index; | ||
| 458 | p_dev->io.BasePort1 = cf->io.win[0].base; | ||
| 459 | p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ? | ||
| 460 | 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 461 | if (!pcmcia_request_io(p_dev, &p_dev->io)) | ||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | return -EINVAL; | ||
| 453 | } | 465 | } |
| 454 | 466 | ||
| 455 | /*====================================================================*/ | 467 | static int simple_config_check_notpicky(struct pcmcia_device *p_dev, |
| 468 | cistpl_cftable_entry_t *cf, | ||
| 469 | void *priv_data) | ||
| 470 | { | ||
| 471 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
| 472 | int j; | ||
| 473 | |||
| 474 | if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
| 475 | p_dev->conf.ConfigIndex = cf->index; | ||
| 476 | for (j = 0; j < 5; j++) { | ||
| 477 | p_dev->io.BasePort1 = base[j]; | ||
| 478 | p_dev->io.IOAddrLines = base[j] ? 16 : 3; | ||
| 479 | if (!pcmcia_request_io(p_dev, &p_dev->io)) | ||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | return -ENODEV; | ||
| 484 | } | ||
| 456 | 485 | ||
| 457 | static int simple_config(struct pcmcia_device *link) | 486 | static int simple_config(struct pcmcia_device *link) |
| 458 | { | 487 | { |
| 459 | static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | ||
| 460 | static const int size_table[2] = { 8, 16 }; | ||
| 461 | struct serial_info *info = link->priv; | 488 | struct serial_info *info = link->priv; |
| 462 | struct serial_cfg_mem *cfg_mem; | ||
| 463 | tuple_t *tuple; | ||
| 464 | u_char *buf; | ||
| 465 | cisparse_t *parse; | ||
| 466 | cistpl_cftable_entry_t *cf; | ||
| 467 | config_info_t config; | 489 | config_info_t config; |
| 468 | int i, j, try; | 490 | int i, try; |
| 469 | int s; | ||
| 470 | |||
| 471 | cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); | ||
| 472 | if (!cfg_mem) | ||
| 473 | return -1; | ||
| 474 | |||
| 475 | tuple = &cfg_mem->tuple; | ||
| 476 | parse = &cfg_mem->parse; | ||
| 477 | cf = &parse->cftable_entry; | ||
| 478 | buf = cfg_mem->buf; | ||
| 479 | 491 | ||
| 480 | /* If the card is already configured, look up the port and irq */ | 492 | /* If the card is already configured, look up the port and irq */ |
| 481 | i = pcmcia_get_configuration_info(link, &config); | 493 | i = pcmcia_get_configuration_info(link, &config); |
| @@ -490,70 +502,28 @@ static int simple_config(struct pcmcia_device *link) | |||
| 490 | info->slave = 1; | 502 | info->slave = 1; |
| 491 | } | 503 | } |
| 492 | if (info->slave) { | 504 | if (info->slave) { |
| 493 | kfree(cfg_mem); | ||
| 494 | return setup_serial(link, info, port, config.AssignedIRQ); | 505 | return setup_serial(link, info, port, config.AssignedIRQ); |
| 495 | } | 506 | } |
| 496 | } | 507 | } |
| 497 | 508 | ||
| 498 | /* First pass: look for a config entry that looks normal. */ | 509 | /* First pass: look for a config entry that looks normal. |
| 499 | tuple->TupleData = (cisdata_t *) buf; | 510 | * Two tries: without IO aliases, then with aliases */ |
| 500 | tuple->TupleOffset = 0; | 511 | for (try = 0; try < 4; try++) |
| 501 | tuple->TupleDataMax = 255; | 512 | if (!pcmcia_loop_config(link, simple_config_check, &try)) |
| 502 | tuple->Attributes = 0; | 513 | goto found_port; |
| 503 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 514 | |
| 504 | /* Two tries: without IO aliases, then with aliases */ | ||
| 505 | for (s = 0; s < 2; s++) { | ||
| 506 | for (try = 0; try < 2; try++) { | ||
| 507 | i = first_tuple(link, tuple, parse); | ||
| 508 | while (i != CS_NO_MORE_ITEMS) { | ||
| 509 | if (i != CS_SUCCESS) | ||
| 510 | goto next_entry; | ||
| 511 | if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
| 512 | link->conf.Vpp = | ||
| 513 | cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
| 514 | if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) && | ||
| 515 | (cf->io.win[0].base != 0)) { | ||
| 516 | link->conf.ConfigIndex = cf->index; | ||
| 517 | link->io.BasePort1 = cf->io.win[0].base; | ||
| 518 | link->io.IOAddrLines = (try == 0) ? | ||
| 519 | 16 : cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 520 | i = pcmcia_request_io(link, &link->io); | ||
| 521 | if (i == CS_SUCCESS) | ||
| 522 | goto found_port; | ||
| 523 | } | ||
| 524 | next_entry: | ||
| 525 | i = next_tuple(link, tuple, parse); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | } | ||
| 529 | /* Second pass: try to find an entry that isn't picky about | 515 | /* Second pass: try to find an entry that isn't picky about |
| 530 | its base address, then try to grab any standard serial port | 516 | its base address, then try to grab any standard serial port |
| 531 | address, and finally try to get any free port. */ | 517 | address, and finally try to get any free port. */ |
| 532 | i = first_tuple(link, tuple, parse); | 518 | if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) |
| 533 | while (i != CS_NO_MORE_ITEMS) { | 519 | goto found_port; |
| 534 | if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && | ||
| 535 | ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { | ||
| 536 | link->conf.ConfigIndex = cf->index; | ||
| 537 | for (j = 0; j < 5; j++) { | ||
| 538 | link->io.BasePort1 = base[j]; | ||
| 539 | link->io.IOAddrLines = base[j] ? 16 : 3; | ||
| 540 | i = pcmcia_request_io(link, &link->io); | ||
| 541 | if (i == CS_SUCCESS) | ||
| 542 | goto found_port; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | i = next_tuple(link, tuple, parse); | ||
| 546 | } | ||
| 547 | 520 | ||
| 548 | found_port: | 521 | printk(KERN_NOTICE |
| 549 | if (i != CS_SUCCESS) { | 522 | "serial_cs: no usable port range found, giving up\n"); |
| 550 | printk(KERN_NOTICE | 523 | cs_error(link, RequestIO, i); |
| 551 | "serial_cs: no usable port range found, giving up\n"); | 524 | return -1; |
| 552 | cs_error(link, RequestIO, i); | ||
| 553 | kfree(cfg_mem); | ||
| 554 | return -1; | ||
| 555 | } | ||
| 556 | 525 | ||
| 526 | found_port: | ||
| 557 | i = pcmcia_request_irq(link, &link->irq); | 527 | i = pcmcia_request_irq(link, &link->irq); |
| 558 | if (i != CS_SUCCESS) { | 528 | if (i != CS_SUCCESS) { |
| 559 | cs_error(link, RequestIRQ, i); | 529 | cs_error(link, RequestIRQ, i); |
| @@ -571,86 +541,72 @@ next_entry: | |||
| 571 | i = pcmcia_request_configuration(link, &link->conf); | 541 | i = pcmcia_request_configuration(link, &link->conf); |
| 572 | if (i != CS_SUCCESS) { | 542 | if (i != CS_SUCCESS) { |
| 573 | cs_error(link, RequestConfiguration, i); | 543 | cs_error(link, RequestConfiguration, i); |
| 574 | kfree(cfg_mem); | ||
| 575 | return -1; | 544 | return -1; |
| 576 | } | 545 | } |
| 577 | kfree(cfg_mem); | ||
| 578 | return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); | 546 | return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); |
| 579 | } | 547 | } |
| 580 | 548 | ||
| 581 | static int multi_config(struct pcmcia_device * link) | 549 | static int multi_config_check(struct pcmcia_device *p_dev, |
| 550 | cistpl_cftable_entry_t *cf, | ||
| 551 | void *priv_data) | ||
| 582 | { | 552 | { |
| 583 | struct serial_info *info = link->priv; | 553 | int *base2 = priv_data; |
| 584 | struct serial_cfg_mem *cfg_mem; | 554 | |
| 585 | tuple_t *tuple; | 555 | /* The quad port cards have bad CIS's, so just look for a |
| 586 | u_char *buf; | 556 | window larger than 8 ports and assume it will be right */ |
| 587 | cisparse_t *parse; | 557 | if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { |
| 588 | cistpl_cftable_entry_t *cf; | 558 | p_dev->conf.ConfigIndex = cf->index; |
| 589 | int i, rc, base2 = 0; | 559 | p_dev->io.BasePort1 = cf->io.win[0].base; |
| 560 | p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 561 | if (!pcmcia_request_io(p_dev, &p_dev->io)) { | ||
| 562 | *base2 = p_dev->io.BasePort1 + 8; | ||
| 563 | return 0; | ||
| 564 | } | ||
| 565 | } | ||
| 566 | return -ENODEV; | ||
| 567 | } | ||
| 590 | 568 | ||
| 591 | cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); | 569 | static int multi_config_check_notpicky(struct pcmcia_device *p_dev, |
| 592 | if (!cfg_mem) | 570 | cistpl_cftable_entry_t *cf, |
| 593 | return -1; | 571 | void *priv_data) |
| 594 | tuple = &cfg_mem->tuple; | 572 | { |
| 595 | parse = &cfg_mem->parse; | 573 | int *base2 = priv_data; |
| 596 | cf = &parse->cftable_entry; | 574 | |
| 597 | buf = cfg_mem->buf; | 575 | if (cf->io.nwin == 2) { |
| 576 | p_dev->conf.ConfigIndex = cf->index; | ||
| 577 | p_dev->io.BasePort1 = cf->io.win[0].base; | ||
| 578 | p_dev->io.BasePort2 = cf->io.win[1].base; | ||
| 579 | p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 580 | if (!pcmcia_request_io(p_dev, &p_dev->io)) { | ||
| 581 | *base2 = p_dev->io.BasePort2; | ||
| 582 | return 0; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | return -ENODEV; | ||
| 586 | } | ||
| 598 | 587 | ||
| 599 | tuple->TupleData = (cisdata_t *) buf; | 588 | static int multi_config(struct pcmcia_device *link) |
| 600 | tuple->TupleOffset = 0; | 589 | { |
| 601 | tuple->TupleDataMax = 255; | 590 | struct serial_info *info = link->priv; |
| 602 | tuple->Attributes = 0; | 591 | int i, base2 = 0; |
| 603 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
| 604 | 592 | ||
| 605 | /* First, look for a generic full-sized window */ | 593 | /* First, look for a generic full-sized window */ |
| 606 | link->io.NumPorts1 = info->multi * 8; | 594 | link->io.NumPorts1 = info->multi * 8; |
| 607 | i = first_tuple(link, tuple, parse); | 595 | if (pcmcia_loop_config(link, multi_config_check, &base2)) { |
| 608 | while (i != CS_NO_MORE_ITEMS) { | 596 | /* If that didn't work, look for two windows */ |
| 609 | /* The quad port cards have bad CIS's, so just look for a | ||
| 610 | window larger than 8 ports and assume it will be right */ | ||
| 611 | if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && | ||
| 612 | (cf->io.win[0].len > 8)) { | ||
| 613 | link->conf.ConfigIndex = cf->index; | ||
| 614 | link->io.BasePort1 = cf->io.win[0].base; | ||
| 615 | link->io.IOAddrLines = | ||
| 616 | cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 617 | i = pcmcia_request_io(link, &link->io); | ||
| 618 | base2 = link->io.BasePort1 + 8; | ||
| 619 | if (i == CS_SUCCESS) | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | i = next_tuple(link, tuple, parse); | ||
| 623 | } | ||
| 624 | |||
| 625 | /* If that didn't work, look for two windows */ | ||
| 626 | if (i != CS_SUCCESS) { | ||
| 627 | link->io.NumPorts1 = link->io.NumPorts2 = 8; | 597 | link->io.NumPorts1 = link->io.NumPorts2 = 8; |
| 628 | info->multi = 2; | 598 | info->multi = 2; |
| 629 | i = first_tuple(link, tuple, parse); | 599 | if (pcmcia_loop_config(link, multi_config_check_notpicky, |
| 630 | while (i != CS_NO_MORE_ITEMS) { | 600 | &base2)) { |
| 631 | if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { | 601 | printk(KERN_NOTICE "serial_cs: no usable port range" |
| 632 | link->conf.ConfigIndex = cf->index; | 602 | "found, giving up\n"); |
| 633 | link->io.BasePort1 = cf->io.win[0].base; | 603 | return -ENODEV; |
| 634 | link->io.BasePort2 = cf->io.win[1].base; | ||
| 635 | link->io.IOAddrLines = | ||
| 636 | cf->io.flags & CISTPL_IO_LINES_MASK; | ||
| 637 | i = pcmcia_request_io(link, &link->io); | ||
| 638 | base2 = link->io.BasePort2; | ||
| 639 | if (i == CS_SUCCESS) | ||
| 640 | break; | ||
| 641 | } | ||
| 642 | i = next_tuple(link, tuple, parse); | ||
| 643 | } | 604 | } |
| 644 | } | 605 | } |
| 645 | 606 | ||
| 646 | if (i != CS_SUCCESS) { | ||
| 647 | cs_error(link, RequestIO, i); | ||
| 648 | rc = -1; | ||
| 649 | goto free_cfg_mem; | ||
| 650 | } | ||
| 651 | |||
| 652 | i = pcmcia_request_irq(link, &link->irq); | 607 | i = pcmcia_request_irq(link, &link->irq); |
| 653 | if (i != CS_SUCCESS) { | 608 | if (i != CS_SUCCESS) { |
| 609 | /* FIXME: comment does not fit, error handling does not fit */ | ||
| 654 | printk(KERN_NOTICE | 610 | printk(KERN_NOTICE |
| 655 | "serial_cs: no usable port range found, giving up\n"); | 611 | "serial_cs: no usable port range found, giving up\n"); |
| 656 | cs_error(link, RequestIRQ, i); | 612 | cs_error(link, RequestIRQ, i); |
| @@ -666,8 +622,7 @@ static int multi_config(struct pcmcia_device * link) | |||
| 666 | i = pcmcia_request_configuration(link, &link->conf); | 622 | i = pcmcia_request_configuration(link, &link->conf); |
| 667 | if (i != CS_SUCCESS) { | 623 | if (i != CS_SUCCESS) { |
| 668 | cs_error(link, RequestConfiguration, i); | 624 | cs_error(link, RequestConfiguration, i); |
| 669 | rc = -1; | 625 | return -ENODEV; |
| 670 | goto free_cfg_mem; | ||
| 671 | } | 626 | } |
| 672 | 627 | ||
| 673 | /* The Oxford Semiconductor OXCF950 cards are in fact single-port: | 628 | /* The Oxford Semiconductor OXCF950 cards are in fact single-port: |
| @@ -678,7 +633,8 @@ static int multi_config(struct pcmcia_device * link) | |||
| 678 | info->prodid == PRODID_POSSIO_GCC)) { | 633 | info->prodid == PRODID_POSSIO_GCC)) { |
| 679 | int err; | 634 | int err; |
| 680 | 635 | ||
| 681 | if (cf->index == 1 || cf->index == 3) { | 636 | if (link->conf.ConfigIndex == 1 || |
| 637 | link->conf.ConfigIndex == 3) { | ||
| 682 | err = setup_serial(link, info, base2, | 638 | err = setup_serial(link, info, base2, |
| 683 | link->irq.AssignedIRQ); | 639 | link->irq.AssignedIRQ); |
| 684 | base2 = link->io.BasePort1; | 640 | base2 = link->io.BasePort1; |
| @@ -695,18 +651,14 @@ static int multi_config(struct pcmcia_device * link) | |||
| 695 | if (info->quirk && info->quirk->wakeup) | 651 | if (info->quirk && info->quirk->wakeup) |
| 696 | info->quirk->wakeup(link); | 652 | info->quirk->wakeup(link); |
| 697 | 653 | ||
| 698 | rc = 0; | 654 | return 0; |
| 699 | goto free_cfg_mem; | ||
| 700 | } | 655 | } |
| 701 | 656 | ||
| 702 | setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); | 657 | setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); |
| 703 | for (i = 0; i < info->multi - 1; i++) | 658 | for (i = 0; i < info->multi - 1; i++) |
| 704 | setup_serial(link, info, base2 + (8 * i), | 659 | setup_serial(link, info, base2 + (8 * i), |
| 705 | link->irq.AssignedIRQ); | 660 | link->irq.AssignedIRQ); |
| 706 | rc = 0; | 661 | return 0; |
| 707 | free_cfg_mem: | ||
| 708 | kfree(cfg_mem); | ||
| 709 | return rc; | ||
| 710 | } | 662 | } |
| 711 | 663 | ||
| 712 | /*====================================================================== | 664 | /*====================================================================== |
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index ff9a29b76336..89c5e40ce3a0 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
| @@ -124,65 +124,57 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) | |||
| 124 | return; | 124 | return; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int ixj_config_check(struct pcmcia_device *p_dev, | ||
| 128 | cistpl_cftable_entry_t *cfg, | ||
| 129 | void *priv_data) | ||
| 130 | { | ||
| 131 | cistpl_cftable_entry_t *dflt = priv_data; | ||
| 132 | |||
| 133 | if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { | ||
| 134 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; | ||
| 135 | p_dev->conf.ConfigIndex = cfg->index; | ||
| 136 | p_dev->io.BasePort1 = io->win[0].base; | ||
| 137 | p_dev->io.NumPorts1 = io->win[0].len; | ||
| 138 | if (io->nwin == 2) { | ||
| 139 | p_dev->io.BasePort2 = io->win[1].base; | ||
| 140 | p_dev->io.NumPorts2 = io->win[1].len; | ||
| 141 | } | ||
| 142 | if (pcmcia_request_io(p_dev, &p_dev->io)) { | ||
| 143 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
| 144 | *dflt = *cfg; | ||
| 145 | } else | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | return -ENODEV; | ||
| 149 | } | ||
| 150 | |||
| 127 | static int ixj_config(struct pcmcia_device * link) | 151 | static int ixj_config(struct pcmcia_device * link) |
| 128 | { | 152 | { |
| 129 | IXJ *j; | 153 | IXJ *j; |
| 130 | ixj_info_t *info; | 154 | ixj_info_t *info; |
| 131 | tuple_t tuple; | 155 | cistpl_cftable_entry_t dflt = { 0 }; |
| 132 | u_short buf[128]; | 156 | |
| 133 | cisparse_t parse; | ||
| 134 | cistpl_cftable_entry_t *cfg = &parse.cftable_entry; | ||
| 135 | cistpl_cftable_entry_t dflt = | ||
| 136 | { | ||
| 137 | 0 | ||
| 138 | }; | ||
| 139 | int last_ret, last_fn; | ||
| 140 | info = link->priv; | 157 | info = link->priv; |
| 141 | DEBUG(0, "ixj_config(0x%p)\n", link); | 158 | DEBUG(0, "ixj_config(0x%p)\n", link); |
| 142 | tuple.TupleData = (cisdata_t *) buf; | ||
| 143 | tuple.TupleOffset = 0; | ||
| 144 | tuple.TupleDataMax = 255; | ||
| 145 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
| 146 | tuple.Attributes = 0; | ||
| 147 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
| 148 | while (1) { | ||
| 149 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || | ||
| 150 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) | ||
| 151 | goto next_entry; | ||
| 152 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
| 153 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
| 154 | link->conf.ConfigIndex = cfg->index; | ||
| 155 | link->io.BasePort1 = io->win[0].base; | ||
| 156 | link->io.NumPorts1 = io->win[0].len; | ||
| 157 | if (io->nwin == 2) { | ||
| 158 | link->io.BasePort2 = io->win[1].base; | ||
| 159 | link->io.NumPorts2 = io->win[1].len; | ||
| 160 | } | ||
| 161 | if (pcmcia_request_io(link, &link->io) != 0) | ||
| 162 | goto next_entry; | ||
| 163 | /* If we've got this far, we're done */ | ||
| 164 | break; | ||
| 165 | } | ||
| 166 | next_entry: | ||
| 167 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
| 168 | dflt = *cfg; | ||
| 169 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); | ||
| 170 | } | ||
| 171 | 159 | ||
| 172 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 160 | if (pcmcia_loop_config(link, ixj_config_check, &dflt)) |
| 161 | goto cs_failed; | ||
| 162 | |||
| 163 | if (pcmcia_request_configuration(link, &link->conf)) | ||
| 164 | goto cs_failed; | ||
| 173 | 165 | ||
| 174 | /* | 166 | /* |
| 175 | * Register the card with the core. | 167 | * Register the card with the core. |
| 176 | */ | 168 | */ |
| 177 | j=ixj_pcmcia_probe(link->io.BasePort1,link->io.BasePort1 + 0x10); | 169 | j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10); |
| 178 | 170 | ||
| 179 | info->ndev = 1; | 171 | info->ndev = 1; |
| 180 | info->node.major = PHONE_MAJOR; | 172 | info->node.major = PHONE_MAJOR; |
| 181 | link->dev_node = &info->node; | 173 | link->dev_node = &info->node; |
| 182 | ixj_get_serial(link, j); | 174 | ixj_get_serial(link, j); |
| 183 | return 0; | 175 | return 0; |
| 176 | |||
| 184 | cs_failed: | 177 | cs_failed: |
| 185 | cs_error(link, last_fn, last_ret); | ||
| 186 | ixj_cs_release(link); | 178 | ixj_cs_release(link); |
| 187 | return -ENODEV; | 179 | return -ENODEV; |
| 188 | } | 180 | } |
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 5da63f535005..9773601bf0bb 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
| @@ -155,88 +155,84 @@ static void sl811_cs_release(struct pcmcia_device * link) | |||
| 155 | platform_device_unregister(&platform_dev); | 155 | platform_device_unregister(&platform_dev); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | struct sl811_css_cfg { | ||
| 159 | cistpl_cftable_entry_t dflt; | ||
| 160 | config_info_t conf; | ||
| 161 | }; | ||
| 162 | |||
| 163 | static int sl811_cs_config_check(struct pcmcia_device *p_dev, | ||
| 164 | cistpl_cftable_entry_t *cfg, | ||
| 165 | void *priv_data) | ||
| 166 | { | ||
| 167 | struct sl811_css_cfg *cfg_mem = priv_data; | ||
| 168 | |||
| 169 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
| 170 | memcpy(&cfg_mem->dflt, cfg, sizeof(cistpl_cftable_entry_t)); | ||
| 171 | |||
| 172 | if (cfg->index == 0) | ||
| 173 | return -ENODEV; | ||
| 174 | |||
| 175 | p_dev->conf.ConfigIndex = cfg->index; | ||
| 176 | |||
| 177 | /* Use power settings for Vcc and Vpp if present */ | ||
| 178 | /* Note that the CIS values need to be rescaled */ | ||
| 179 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
| 180 | if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != | ||
| 181 | cfg_mem->conf.Vcc) | ||
| 182 | return -ENODEV; | ||
| 183 | } else if (cfg_mem->dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
| 184 | if (cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM]/10000 | ||
| 185 | != cfg_mem->conf.Vcc) | ||
| 186 | return -ENODEV; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
| 190 | p_dev->conf.Vpp = | ||
| 191 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
| 192 | else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
| 193 | p_dev->conf.Vpp = | ||
| 194 | cfg_mem->dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
| 195 | |||
| 196 | /* we need an interrupt */ | ||
| 197 | if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1) | ||
| 198 | p_dev->conf.Attributes |= CONF_ENABLE_IRQ; | ||
| 199 | |||
| 200 | /* IO window settings */ | ||
| 201 | p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; | ||
| 202 | if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) { | ||
| 203 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->dflt.io; | ||
| 204 | |||
| 205 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 206 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
| 207 | p_dev->io.BasePort1 = io->win[0].base; | ||
| 208 | p_dev->io.NumPorts1 = io->win[0].len; | ||
| 209 | |||
| 210 | return pcmcia_request_io(p_dev, &p_dev->io); | ||
| 211 | } | ||
| 212 | pcmcia_disable_device(p_dev); | ||
| 213 | return -ENODEV; | ||
| 214 | } | ||
| 215 | |||
| 216 | |||
| 158 | static int sl811_cs_config(struct pcmcia_device *link) | 217 | static int sl811_cs_config(struct pcmcia_device *link) |
| 159 | { | 218 | { |
| 160 | struct device *parent = &handle_to_dev(link); | 219 | struct device *parent = &handle_to_dev(link); |
| 161 | local_info_t *dev = link->priv; | 220 | local_info_t *dev = link->priv; |
| 162 | tuple_t tuple; | ||
| 163 | cisparse_t parse; | ||
| 164 | int last_fn, last_ret; | 221 | int last_fn, last_ret; |
| 165 | u_char buf[64]; | 222 | struct sl811_css_cfg *cfg_mem; |
| 166 | config_info_t conf; | ||
| 167 | cistpl_cftable_entry_t dflt = { 0 }; | ||
| 168 | 223 | ||
| 169 | DBG(0, "sl811_cs_config(0x%p)\n", link); | 224 | DBG(0, "sl811_cs_config(0x%p)\n", link); |
| 170 | 225 | ||
| 226 | cfg_mem = kzalloc(sizeof(struct sl811_css_cfg), GFP_KERNEL); | ||
| 227 | if (!cfg_mem) | ||
| 228 | return -ENOMEM; | ||
| 229 | |||
| 171 | /* Look up the current Vcc */ | 230 | /* Look up the current Vcc */ |
| 172 | CS_CHECK(GetConfigurationInfo, | 231 | CS_CHECK(GetConfigurationInfo, |
| 173 | pcmcia_get_configuration_info(link, &conf)); | 232 | pcmcia_get_configuration_info(link, &cfg_mem->conf)); |
| 174 | |||
| 175 | tuple.Attributes = 0; | ||
| 176 | tuple.TupleData = buf; | ||
| 177 | tuple.TupleDataMax = sizeof(buf); | ||
| 178 | tuple.TupleOffset = 0; | ||
| 179 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
| 180 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
| 181 | while (1) { | ||
| 182 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
| 183 | |||
| 184 | if (pcmcia_get_tuple_data(link, &tuple) != 0 | ||
| 185 | || pcmcia_parse_tuple(link, &tuple, &parse) | ||
| 186 | != 0) | ||
| 187 | goto next_entry; | ||
| 188 | |||
| 189 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { | ||
| 190 | dflt = *cfg; | ||
| 191 | } | ||
| 192 | 233 | ||
| 193 | if (cfg->index == 0) | 234 | if (pcmcia_loop_config(link, sl811_cs_config_check, cfg_mem)) |
| 194 | goto next_entry; | 235 | return -ENODEV; |
| 195 | |||
| 196 | link->conf.ConfigIndex = cfg->index; | ||
| 197 | |||
| 198 | /* Use power settings for Vcc and Vpp if present */ | ||
| 199 | /* Note that the CIS values need to be rescaled */ | ||
| 200 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
| 201 | if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 | ||
| 202 | != conf.Vcc) | ||
| 203 | goto next_entry; | ||
| 204 | } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { | ||
| 205 | if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000 | ||
| 206 | != conf.Vcc) | ||
| 207 | goto next_entry; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
| 211 | link->conf.Vpp = | ||
| 212 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
| 213 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | ||
| 214 | link->conf.Vpp = | ||
| 215 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | ||
| 216 | |||
| 217 | /* we need an interrupt */ | ||
| 218 | if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) | ||
| 219 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
| 220 | |||
| 221 | /* IO window settings */ | ||
| 222 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
| 223 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
| 224 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
| 225 | |||
| 226 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | ||
| 227 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
| 228 | link->io.BasePort1 = io->win[0].base; | ||
| 229 | link->io.NumPorts1 = io->win[0].len; | ||
| 230 | |||
| 231 | if (pcmcia_request_io(link, &link->io) != 0) | ||
| 232 | goto next_entry; | ||
| 233 | } | ||
| 234 | break; | ||
| 235 | |||
| 236 | next_entry: | ||
| 237 | pcmcia_disable_device(link); | ||
| 238 | last_ret = pcmcia_get_next_tuple(link, &tuple); | ||
| 239 | } | ||
| 240 | 236 | ||
| 241 | /* require an IRQ and two registers */ | 237 | /* require an IRQ and two registers */ |
| 242 | if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) | 238 | if (!link->io.NumPorts1 || link->io.NumPorts1 < 2) |
| @@ -269,8 +265,10 @@ cs_failed: | |||
| 269 | printk("sl811_cs_config failed\n"); | 265 | printk("sl811_cs_config failed\n"); |
| 270 | cs_error(link, last_fn, last_ret); | 266 | cs_error(link, last_fn, last_ret); |
| 271 | sl811_cs_release(link); | 267 | sl811_cs_release(link); |
| 268 | kfree(cfg_mem); | ||
| 272 | return -ENODEV; | 269 | return -ENODEV; |
| 273 | } | 270 | } |
| 271 | kfree(cfg_mem); | ||
| 274 | return 0; | 272 | return 0; |
| 275 | } | 273 | } |
| 276 | 274 | ||
