diff options
Diffstat (limited to 'drivers/serial/serial_cs.c')
-rw-r--r-- | drivers/serial/serial_cs.c | 143 |
1 files changed, 41 insertions, 102 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7c7914f5fa02..fc413f0f8dd2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -54,14 +54,6 @@ | |||
54 | 54 | ||
55 | #include "8250.h" | 55 | #include "8250.h" |
56 | 56 | ||
57 | #ifdef PCMCIA_DEBUG | ||
58 | static int pc_debug = PCMCIA_DEBUG; | ||
59 | module_param(pc_debug, int, 0644); | ||
60 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) | ||
61 | static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; | ||
62 | #else | ||
63 | #define DEBUG(n, args...) | ||
64 | #endif | ||
65 | 57 | ||
66 | /*====================================================================*/ | 58 | /*====================================================================*/ |
67 | 59 | ||
@@ -121,24 +113,20 @@ static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_ | |||
121 | static int quirk_post_ibm(struct pcmcia_device *link) | 113 | static int quirk_post_ibm(struct pcmcia_device *link) |
122 | { | 114 | { |
123 | conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; | 115 | conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; |
124 | int last_ret, last_fn; | 116 | int ret; |
117 | |||
118 | ret = pcmcia_access_configuration_register(link, ®); | ||
119 | if (ret) | ||
120 | goto failed; | ||
125 | 121 | ||
126 | last_ret = pcmcia_access_configuration_register(link, ®); | ||
127 | if (last_ret) { | ||
128 | last_fn = AccessConfigurationRegister; | ||
129 | goto cs_failed; | ||
130 | } | ||
131 | reg.Action = CS_WRITE; | 122 | reg.Action = CS_WRITE; |
132 | reg.Value = reg.Value | 1; | 123 | reg.Value = reg.Value | 1; |
133 | last_ret = pcmcia_access_configuration_register(link, ®); | 124 | ret = pcmcia_access_configuration_register(link, ®); |
134 | if (last_ret) { | 125 | if (ret) |
135 | last_fn = AccessConfigurationRegister; | 126 | goto failed; |
136 | goto cs_failed; | ||
137 | } | ||
138 | return 0; | 127 | return 0; |
139 | 128 | ||
140 | cs_failed: | 129 | failed: |
141 | cs_error(link, last_fn, last_ret); | ||
142 | return -ENODEV; | 130 | return -ENODEV; |
143 | } | 131 | } |
144 | 132 | ||
@@ -283,7 +271,7 @@ static void serial_remove(struct pcmcia_device *link) | |||
283 | struct serial_info *info = link->priv; | 271 | struct serial_info *info = link->priv; |
284 | int i; | 272 | int i; |
285 | 273 | ||
286 | DEBUG(0, "serial_release(0x%p)\n", link); | 274 | dev_dbg(&link->dev, "serial_release\n"); |
287 | 275 | ||
288 | /* | 276 | /* |
289 | * Recheck to see if the device is still configured. | 277 | * Recheck to see if the device is still configured. |
@@ -334,7 +322,7 @@ static int serial_probe(struct pcmcia_device *link) | |||
334 | { | 322 | { |
335 | struct serial_info *info; | 323 | struct serial_info *info; |
336 | 324 | ||
337 | DEBUG(0, "serial_attach()\n"); | 325 | dev_dbg(&link->dev, "serial_attach()\n"); |
338 | 326 | ||
339 | /* Create new serial device */ | 327 | /* Create new serial device */ |
340 | info = kzalloc(sizeof (*info), GFP_KERNEL); | 328 | info = kzalloc(sizeof (*info), GFP_KERNEL); |
@@ -346,7 +334,6 @@ static int serial_probe(struct pcmcia_device *link) | |||
346 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 334 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
347 | link->io.NumPorts1 = 8; | 335 | link->io.NumPorts1 = 8; |
348 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; | 336 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
349 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
350 | link->conf.Attributes = CONF_ENABLE_IRQ; | 337 | link->conf.Attributes = CONF_ENABLE_IRQ; |
351 | if (do_sound) { | 338 | if (do_sound) { |
352 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 339 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
@@ -370,7 +357,7 @@ static void serial_detach(struct pcmcia_device *link) | |||
370 | { | 357 | { |
371 | struct serial_info *info = link->priv; | 358 | struct serial_info *info = link->priv; |
372 | 359 | ||
373 | DEBUG(0, "serial_detach(0x%p)\n", link); | 360 | dev_dbg(&link->dev, "serial_detach\n"); |
374 | 361 | ||
375 | /* | 362 | /* |
376 | * Ensure any outstanding scheduled tasks are completed. | 363 | * Ensure any outstanding scheduled tasks are completed. |
@@ -399,7 +386,7 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
399 | port.irq = irq; | 386 | port.irq = irq; |
400 | port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; | 387 | port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; |
401 | port.uartclk = 1843200; | 388 | port.uartclk = 1843200; |
402 | port.dev = &handle_to_dev(handle); | 389 | port.dev = &handle->dev; |
403 | if (buggy_uart) | 390 | if (buggy_uart) |
404 | port.flags |= UPF_BUGGY_UART; | 391 | port.flags |= UPF_BUGGY_UART; |
405 | 392 | ||
@@ -426,21 +413,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, | |||
426 | 413 | ||
427 | /*====================================================================*/ | 414 | /*====================================================================*/ |
428 | 415 | ||
429 | static int | ||
430 | first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) | ||
431 | { | ||
432 | int i; | ||
433 | i = pcmcia_get_first_tuple(handle, tuple); | ||
434 | if (i != 0) | ||
435 | return i; | ||
436 | i = pcmcia_get_tuple_data(handle, tuple); | ||
437 | if (i != 0) | ||
438 | return i; | ||
439 | return pcmcia_parse_tuple(tuple, parse); | ||
440 | } | ||
441 | |||
442 | /*====================================================================*/ | ||
443 | |||
444 | static int simple_config_check(struct pcmcia_device *p_dev, | 416 | static int simple_config_check(struct pcmcia_device *p_dev, |
445 | cistpl_cftable_entry_t *cf, | 417 | cistpl_cftable_entry_t *cf, |
446 | cistpl_cftable_entry_t *dflt, | 418 | cistpl_cftable_entry_t *dflt, |
@@ -522,15 +494,13 @@ static int simple_config(struct pcmcia_device *link) | |||
522 | 494 | ||
523 | printk(KERN_NOTICE | 495 | printk(KERN_NOTICE |
524 | "serial_cs: no usable port range found, giving up\n"); | 496 | "serial_cs: no usable port range found, giving up\n"); |
525 | cs_error(link, RequestIO, i); | ||
526 | return -1; | 497 | return -1; |
527 | 498 | ||
528 | found_port: | 499 | found_port: |
529 | i = pcmcia_request_irq(link, &link->irq); | 500 | i = pcmcia_request_irq(link, &link->irq); |
530 | if (i != 0) { | 501 | if (i != 0) |
531 | cs_error(link, RequestIRQ, i); | ||
532 | link->irq.AssignedIRQ = 0; | 502 | link->irq.AssignedIRQ = 0; |
533 | } | 503 | |
534 | if (info->multi && (info->manfid == MANFID_3COM)) | 504 | if (info->multi && (info->manfid == MANFID_3COM)) |
535 | link->conf.ConfigIndex &= ~(0x08); | 505 | link->conf.ConfigIndex &= ~(0x08); |
536 | 506 | ||
@@ -541,10 +511,8 @@ found_port: | |||
541 | info->quirk->config(link); | 511 | info->quirk->config(link); |
542 | 512 | ||
543 | i = pcmcia_request_configuration(link, &link->conf); | 513 | i = pcmcia_request_configuration(link, &link->conf); |
544 | if (i != 0) { | 514 | if (i != 0) |
545 | cs_error(link, RequestConfiguration, i); | ||
546 | return -1; | 515 | return -1; |
547 | } | ||
548 | return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); | 516 | return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); |
549 | } | 517 | } |
550 | 518 | ||
@@ -613,7 +581,6 @@ static int multi_config(struct pcmcia_device *link) | |||
613 | /* FIXME: comment does not fit, error handling does not fit */ | 581 | /* FIXME: comment does not fit, error handling does not fit */ |
614 | printk(KERN_NOTICE | 582 | printk(KERN_NOTICE |
615 | "serial_cs: no usable port range found, giving up\n"); | 583 | "serial_cs: no usable port range found, giving up\n"); |
616 | cs_error(link, RequestIRQ, i); | ||
617 | link->irq.AssignedIRQ = 0; | 584 | link->irq.AssignedIRQ = 0; |
618 | } | 585 | } |
619 | 586 | ||
@@ -624,10 +591,8 @@ static int multi_config(struct pcmcia_device *link) | |||
624 | info->quirk->config(link); | 591 | info->quirk->config(link); |
625 | 592 | ||
626 | i = pcmcia_request_configuration(link, &link->conf); | 593 | i = pcmcia_request_configuration(link, &link->conf); |
627 | if (i != 0) { | 594 | if (i != 0) |
628 | cs_error(link, RequestConfiguration, i); | ||
629 | return -ENODEV; | 595 | return -ENODEV; |
630 | } | ||
631 | 596 | ||
632 | /* The Oxford Semiconductor OXCF950 cards are in fact single-port: | 597 | /* The Oxford Semiconductor OXCF950 cards are in fact single-port: |
633 | * 8 registers are for the UART, the others are extra registers. | 598 | * 8 registers are for the UART, the others are extra registers. |
@@ -665,6 +630,25 @@ static int multi_config(struct pcmcia_device *link) | |||
665 | return 0; | 630 | return 0; |
666 | } | 631 | } |
667 | 632 | ||
633 | static int serial_check_for_multi(struct pcmcia_device *p_dev, | ||
634 | cistpl_cftable_entry_t *cf, | ||
635 | cistpl_cftable_entry_t *dflt, | ||
636 | unsigned int vcc, | ||
637 | void *priv_data) | ||
638 | { | ||
639 | struct serial_info *info = p_dev->priv; | ||
640 | |||
641 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
642 | info->multi = cf->io.win[0].len >> 3; | ||
643 | |||
644 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
645 | (cf->io.win[1].len == 8)) | ||
646 | info->multi = 2; | ||
647 | |||
648 | return 0; /* break */ | ||
649 | } | ||
650 | |||
651 | |||
668 | /*====================================================================== | 652 | /*====================================================================== |
669 | 653 | ||
670 | serial_config() is scheduled to run after a CARD_INSERTION event | 654 | serial_config() is scheduled to run after a CARD_INSERTION event |
@@ -676,46 +660,14 @@ static int multi_config(struct pcmcia_device *link) | |||
676 | static int serial_config(struct pcmcia_device * link) | 660 | static int serial_config(struct pcmcia_device * link) |
677 | { | 661 | { |
678 | struct serial_info *info = link->priv; | 662 | struct serial_info *info = link->priv; |
679 | struct serial_cfg_mem *cfg_mem; | 663 | int i; |
680 | tuple_t *tuple; | ||
681 | u_char *buf; | ||
682 | cisparse_t *parse; | ||
683 | cistpl_cftable_entry_t *cf; | ||
684 | int i, last_ret, last_fn; | ||
685 | |||
686 | DEBUG(0, "serial_config(0x%p)\n", link); | ||
687 | |||
688 | cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); | ||
689 | if (!cfg_mem) | ||
690 | goto failed; | ||
691 | 664 | ||
692 | tuple = &cfg_mem->tuple; | 665 | dev_dbg(&link->dev, "serial_config\n"); |
693 | parse = &cfg_mem->parse; | ||
694 | cf = &parse->cftable_entry; | ||
695 | buf = cfg_mem->buf; | ||
696 | |||
697 | tuple->TupleData = (cisdata_t *) buf; | ||
698 | tuple->TupleOffset = 0; | ||
699 | tuple->TupleDataMax = 255; | ||
700 | tuple->Attributes = 0; | ||
701 | |||
702 | /* Get configuration register information */ | ||
703 | tuple->DesiredTuple = CISTPL_CONFIG; | ||
704 | last_ret = first_tuple(link, tuple, parse); | ||
705 | if (last_ret != 0) { | ||
706 | last_fn = ParseTuple; | ||
707 | goto cs_failed; | ||
708 | } | ||
709 | link->conf.ConfigBase = parse->config.base; | ||
710 | link->conf.Present = parse->config.rmask[0]; | ||
711 | 666 | ||
712 | /* Is this a compliant multifunction card? */ | 667 | /* Is this a compliant multifunction card? */ |
713 | tuple->DesiredTuple = CISTPL_LONGLINK_MFC; | 668 | info->multi = (link->socket->functions > 1); |
714 | tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; | ||
715 | info->multi = (first_tuple(link, tuple, parse) == 0); | ||
716 | 669 | ||
717 | /* Is this a multiport card? */ | 670 | /* Is this a multiport card? */ |
718 | tuple->DesiredTuple = CISTPL_MANFID; | ||
719 | info->manfid = link->manf_id; | 671 | info->manfid = link->manf_id; |
720 | info->prodid = link->card_id; | 672 | info->prodid = link->card_id; |
721 | 673 | ||
@@ -730,20 +682,11 @@ static int serial_config(struct pcmcia_device * link) | |||
730 | 682 | ||
731 | /* Another check for dual-serial cards: look for either serial or | 683 | /* Another check for dual-serial cards: look for either serial or |
732 | multifunction cards that ask for appropriate IO port ranges */ | 684 | multifunction cards that ask for appropriate IO port ranges */ |
733 | tuple->DesiredTuple = CISTPL_FUNCID; | ||
734 | if ((info->multi == 0) && | 685 | if ((info->multi == 0) && |
735 | (link->has_func_id) && | 686 | (link->has_func_id) && |
736 | ((link->func_id == CISTPL_FUNCID_MULTI) || | 687 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
737 | (link->func_id == CISTPL_FUNCID_SERIAL))) { | 688 | (link->func_id == CISTPL_FUNCID_SERIAL))) |
738 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 689 | pcmcia_loop_config(link, serial_check_for_multi, info); |
739 | if (first_tuple(link, tuple, parse) == 0) { | ||
740 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | ||
741 | info->multi = cf->io.win[0].len >> 3; | ||
742 | if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && | ||
743 | (cf->io.win[1].len == 8)) | ||
744 | info->multi = 2; | ||
745 | } | ||
746 | } | ||
747 | 690 | ||
748 | /* | 691 | /* |
749 | * Apply any multi-port quirk. | 692 | * Apply any multi-port quirk. |
@@ -768,14 +711,10 @@ static int serial_config(struct pcmcia_device * link) | |||
768 | goto failed; | 711 | goto failed; |
769 | 712 | ||
770 | link->dev_node = &info->node[0]; | 713 | link->dev_node = &info->node[0]; |
771 | kfree(cfg_mem); | ||
772 | return 0; | 714 | return 0; |
773 | 715 | ||
774 | cs_failed: | ||
775 | cs_error(link, last_fn, last_ret); | ||
776 | failed: | 716 | failed: |
777 | serial_remove(link); | 717 | serial_remove(link); |
778 | kfree(cfg_mem); | ||
779 | return -ENODEV; | 718 | return -ENODEV; |
780 | } | 719 | } |
781 | 720 | ||