diff options
Diffstat (limited to 'drivers/net/pcmcia/pcnet_cs.c')
-rw-r--r-- | drivers/net/pcmcia/pcnet_cs.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index ebc1ae6bcbe5..e40d6301aa7a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -310,7 +310,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) | |||
310 | req.Base = 0; req.Size = 0; | 310 | req.Base = 0; req.Size = 0; |
311 | req.AccessSpeed = 0; | 311 | req.AccessSpeed = 0; |
312 | i = pcmcia_request_window(&link, &req, &link->win); | 312 | i = pcmcia_request_window(&link, &req, &link->win); |
313 | if (i != CS_SUCCESS) { | 313 | if (i != 0) { |
314 | cs_error(link, RequestWindow, i); | 314 | cs_error(link, RequestWindow, i); |
315 | return NULL; | 315 | return NULL; |
316 | } | 316 | } |
@@ -333,7 +333,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link) | |||
333 | 333 | ||
334 | iounmap(virt); | 334 | iounmap(virt); |
335 | j = pcmcia_release_window(link->win); | 335 | j = pcmcia_release_window(link->win); |
336 | if (j != CS_SUCCESS) | 336 | if (j != 0) |
337 | cs_error(link, ReleaseWindow, j); | 337 | cs_error(link, ReleaseWindow, j); |
338 | return (i < NR_INFO) ? hw_info+i : NULL; | 338 | return (i < NR_INFO) ? hw_info+i : NULL; |
339 | } /* get_hwinfo */ | 339 | } /* get_hwinfo */ |
@@ -504,7 +504,8 @@ static int try_io_port(struct pcmcia_device *link) | |||
504 | link->io.BasePort1 = j ^ 0x300; | 504 | link->io.BasePort1 = j ^ 0x300; |
505 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | 505 | link->io.BasePort2 = (j ^ 0x300) + 0x10; |
506 | ret = pcmcia_request_io(link, &link->io); | 506 | ret = pcmcia_request_io(link, &link->io); |
507 | if (ret == CS_SUCCESS) return ret; | 507 | if (ret == 0) |
508 | return ret; | ||
508 | } | 509 | } |
509 | return ret; | 510 | return ret; |
510 | } else { | 511 | } else { |
@@ -512,58 +513,53 @@ static int try_io_port(struct pcmcia_device *link) | |||
512 | } | 513 | } |
513 | } | 514 | } |
514 | 515 | ||
516 | static int pcnet_confcheck(struct pcmcia_device *p_dev, | ||
517 | cistpl_cftable_entry_t *cfg, | ||
518 | cistpl_cftable_entry_t *dflt, | ||
519 | unsigned int vcc, | ||
520 | void *priv_data) | ||
521 | { | ||
522 | int *has_shmem = priv_data; | ||
523 | int i; | ||
524 | cistpl_io_t *io = &cfg->io; | ||
525 | |||
526 | if (cfg->index == 0 || cfg->io.nwin == 0) | ||
527 | return -EINVAL; | ||
528 | |||
529 | /* For multifunction cards, by convention, we configure the | ||
530 | network function with window 0, and serial with window 1 */ | ||
531 | if (io->nwin > 1) { | ||
532 | i = (io->win[1].len > io->win[0].len); | ||
533 | p_dev->io.BasePort2 = io->win[1-i].base; | ||
534 | p_dev->io.NumPorts2 = io->win[1-i].len; | ||
535 | } else { | ||
536 | i = p_dev->io.NumPorts2 = 0; | ||
537 | } | ||
538 | |||
539 | *has_shmem = ((cfg->mem.nwin == 1) && | ||
540 | (cfg->mem.win[0].len >= 0x4000)); | ||
541 | p_dev->io.BasePort1 = io->win[i].base; | ||
542 | p_dev->io.NumPorts1 = io->win[i].len; | ||
543 | p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
544 | if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32) | ||
545 | return try_io_port(p_dev); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
515 | static int pcnet_config(struct pcmcia_device *link) | 550 | static int pcnet_config(struct pcmcia_device *link) |
516 | { | 551 | { |
517 | struct net_device *dev = link->priv; | 552 | struct net_device *dev = link->priv; |
518 | pcnet_dev_t *info = PRIV(dev); | 553 | pcnet_dev_t *info = PRIV(dev); |
519 | tuple_t tuple; | 554 | int last_ret, last_fn, start_pg, stop_pg, cm_offset; |
520 | cisparse_t parse; | ||
521 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; | ||
522 | int has_shmem = 0; | 555 | int has_shmem = 0; |
523 | u_short buf[64]; | ||
524 | hw_info_t *local_hw_info; | 556 | hw_info_t *local_hw_info; |
525 | DECLARE_MAC_BUF(mac); | 557 | DECLARE_MAC_BUF(mac); |
526 | 558 | ||
527 | DEBUG(0, "pcnet_config(0x%p)\n", link); | 559 | DEBUG(0, "pcnet_config(0x%p)\n", link); |
528 | 560 | ||
529 | tuple.TupleData = (cisdata_t *)buf; | 561 | last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); |
530 | tuple.TupleDataMax = sizeof(buf); | 562 | if (last_ret) { |
531 | tuple.TupleOffset = 0; | ||
532 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
533 | tuple.Attributes = 0; | ||
534 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
535 | while (last_ret == CS_SUCCESS) { | ||
536 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
537 | cistpl_io_t *io = &(parse.cftable_entry.io); | ||
538 | |||
539 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || | ||
540 | pcmcia_parse_tuple(link, &tuple, &parse) != 0 || | ||
541 | cfg->index == 0 || cfg->io.nwin == 0) | ||
542 | goto next_entry; | ||
543 | |||
544 | link->conf.ConfigIndex = cfg->index; | ||
545 | /* For multifunction cards, by convention, we configure the | ||
546 | network function with window 0, and serial with window 1 */ | ||
547 | if (io->nwin > 1) { | ||
548 | i = (io->win[1].len > io->win[0].len); | ||
549 | link->io.BasePort2 = io->win[1-i].base; | ||
550 | link->io.NumPorts2 = io->win[1-i].len; | ||
551 | } else { | ||
552 | i = link->io.NumPorts2 = 0; | ||
553 | } | ||
554 | has_shmem = ((cfg->mem.nwin == 1) && | ||
555 | (cfg->mem.win[0].len >= 0x4000)); | ||
556 | link->io.BasePort1 = io->win[i].base; | ||
557 | link->io.NumPorts1 = io->win[i].len; | ||
558 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | ||
559 | if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) { | ||
560 | last_ret = try_io_port(link); | ||
561 | if (last_ret == CS_SUCCESS) break; | ||
562 | } | ||
563 | next_entry: | ||
564 | last_ret = pcmcia_get_next_tuple(link, &tuple); | ||
565 | } | ||
566 | if (last_ret != CS_SUCCESS) { | ||
567 | cs_error(link, RequestIO, last_ret); | 563 | cs_error(link, RequestIO, last_ret); |
568 | goto failed; | 564 | goto failed; |
569 | } | 565 | } |