diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-05 18:22:26 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-05 18:22:26 -0500 |
commit | 28b4d5cc17c20786848cdc07b7ea237a309776bb (patch) | |
tree | bae406a4b17229dcce7c11be5073f7a67665e477 /drivers/ssb | |
parent | d29cecda036f251aee4947f47eea0fe9ed8cc931 (diff) | |
parent | 96fa2b508d2d3fe040cf4ef2fffb955f0a537ea1 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/wireless/ray_cs.c
Diffstat (limited to 'drivers/ssb')
-rw-r--r-- | drivers/ssb/pcmcia.c | 232 |
1 files changed, 118 insertions, 114 deletions
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index 100e7a5c5ea1..e72f4046a5e0 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c | |||
@@ -617,136 +617,140 @@ static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size) | |||
617 | } \ | 617 | } \ |
618 | } while (0) | 618 | } while (0) |
619 | 619 | ||
620 | int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | 620 | static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev, |
621 | struct ssb_init_invariants *iv) | 621 | tuple_t *tuple, |
622 | void *priv) | ||
622 | { | 623 | { |
623 | tuple_t tuple; | 624 | struct ssb_sprom *sprom = priv; |
624 | int res; | 625 | |
625 | unsigned char buf[32]; | 626 | if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) |
627 | return -EINVAL; | ||
628 | if (tuple->TupleDataLen != ETH_ALEN + 2) | ||
629 | return -EINVAL; | ||
630 | if (tuple->TupleData[1] != ETH_ALEN) | ||
631 | return -EINVAL; | ||
632 | memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN); | ||
633 | return 0; | ||
634 | }; | ||
635 | |||
636 | static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, | ||
637 | tuple_t *tuple, | ||
638 | void *priv) | ||
639 | { | ||
640 | struct ssb_init_invariants *iv = priv; | ||
626 | struct ssb_sprom *sprom = &iv->sprom; | 641 | struct ssb_sprom *sprom = &iv->sprom; |
627 | struct ssb_boardinfo *bi = &iv->boardinfo; | 642 | struct ssb_boardinfo *bi = &iv->boardinfo; |
628 | const char *error_description; | 643 | const char *error_description; |
629 | 644 | ||
645 | GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1"); | ||
646 | switch (tuple->TupleData[0]) { | ||
647 | case SSB_PCMCIA_CIS_ID: | ||
648 | GOTO_ERROR_ON((tuple->TupleDataLen != 5) && | ||
649 | (tuple->TupleDataLen != 7), | ||
650 | "id tpl size"); | ||
651 | bi->vendor = tuple->TupleData[1] | | ||
652 | ((u16)tuple->TupleData[2] << 8); | ||
653 | break; | ||
654 | case SSB_PCMCIA_CIS_BOARDREV: | ||
655 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
656 | "boardrev tpl size"); | ||
657 | sprom->board_rev = tuple->TupleData[1]; | ||
658 | break; | ||
659 | case SSB_PCMCIA_CIS_PA: | ||
660 | GOTO_ERROR_ON((tuple->TupleDataLen != 9) && | ||
661 | (tuple->TupleDataLen != 10), | ||
662 | "pa tpl size"); | ||
663 | sprom->pa0b0 = tuple->TupleData[1] | | ||
664 | ((u16)tuple->TupleData[2] << 8); | ||
665 | sprom->pa0b1 = tuple->TupleData[3] | | ||
666 | ((u16)tuple->TupleData[4] << 8); | ||
667 | sprom->pa0b2 = tuple->TupleData[5] | | ||
668 | ((u16)tuple->TupleData[6] << 8); | ||
669 | sprom->itssi_a = tuple->TupleData[7]; | ||
670 | sprom->itssi_bg = tuple->TupleData[7]; | ||
671 | sprom->maxpwr_a = tuple->TupleData[8]; | ||
672 | sprom->maxpwr_bg = tuple->TupleData[8]; | ||
673 | break; | ||
674 | case SSB_PCMCIA_CIS_OEMNAME: | ||
675 | /* We ignore this. */ | ||
676 | break; | ||
677 | case SSB_PCMCIA_CIS_CCODE: | ||
678 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
679 | "ccode tpl size"); | ||
680 | sprom->country_code = tuple->TupleData[1]; | ||
681 | break; | ||
682 | case SSB_PCMCIA_CIS_ANTENNA: | ||
683 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
684 | "ant tpl size"); | ||
685 | sprom->ant_available_a = tuple->TupleData[1]; | ||
686 | sprom->ant_available_bg = tuple->TupleData[1]; | ||
687 | break; | ||
688 | case SSB_PCMCIA_CIS_ANTGAIN: | ||
689 | GOTO_ERROR_ON(tuple->TupleDataLen != 2, | ||
690 | "antg tpl size"); | ||
691 | sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1]; | ||
692 | sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1]; | ||
693 | sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1]; | ||
694 | sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1]; | ||
695 | sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1]; | ||
696 | sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1]; | ||
697 | sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1]; | ||
698 | sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1]; | ||
699 | break; | ||
700 | case SSB_PCMCIA_CIS_BFLAGS: | ||
701 | GOTO_ERROR_ON((tuple->TupleDataLen != 3) && | ||
702 | (tuple->TupleDataLen != 5), | ||
703 | "bfl tpl size"); | ||
704 | sprom->boardflags_lo = tuple->TupleData[1] | | ||
705 | ((u16)tuple->TupleData[2] << 8); | ||
706 | break; | ||
707 | case SSB_PCMCIA_CIS_LEDS: | ||
708 | GOTO_ERROR_ON(tuple->TupleDataLen != 5, | ||
709 | "leds tpl size"); | ||
710 | sprom->gpio0 = tuple->TupleData[1]; | ||
711 | sprom->gpio1 = tuple->TupleData[2]; | ||
712 | sprom->gpio2 = tuple->TupleData[3]; | ||
713 | sprom->gpio3 = tuple->TupleData[4]; | ||
714 | break; | ||
715 | } | ||
716 | return -ENOSPC; /* continue with next entry */ | ||
717 | |||
718 | error: | ||
719 | ssb_printk(KERN_ERR PFX | ||
720 | "PCMCIA: Failed to fetch device invariants: %s\n", | ||
721 | error_description); | ||
722 | return -ENODEV; | ||
723 | } | ||
724 | |||
725 | |||
726 | int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | ||
727 | struct ssb_init_invariants *iv) | ||
728 | { | ||
729 | struct ssb_sprom *sprom = &iv->sprom; | ||
730 | int res; | ||
731 | |||
630 | memset(sprom, 0xFF, sizeof(*sprom)); | 732 | memset(sprom, 0xFF, sizeof(*sprom)); |
631 | sprom->revision = 1; | 733 | sprom->revision = 1; |
632 | sprom->boardflags_lo = 0; | 734 | sprom->boardflags_lo = 0; |
633 | sprom->boardflags_hi = 0; | 735 | sprom->boardflags_hi = 0; |
634 | 736 | ||
635 | /* First fetch the MAC address. */ | 737 | /* First fetch the MAC address. */ |
636 | memset(&tuple, 0, sizeof(tuple)); | 738 | res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, |
637 | tuple.DesiredTuple = CISTPL_FUNCE; | 739 | ssb_pcmcia_get_mac, sprom); |
638 | tuple.TupleData = buf; | 740 | if (res != 0) { |
639 | tuple.TupleDataMax = sizeof(buf); | 741 | ssb_printk(KERN_ERR PFX |
640 | res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); | 742 | "PCMCIA: Failed to fetch MAC address\n"); |
641 | GOTO_ERROR_ON(res != 0, "MAC first tpl"); | 743 | return -ENODEV; |
642 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
643 | GOTO_ERROR_ON(res != 0, "MAC first tpl data"); | ||
644 | while (1) { | ||
645 | GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1"); | ||
646 | if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID) | ||
647 | break; | ||
648 | res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); | ||
649 | GOTO_ERROR_ON(res != 0, "MAC next tpl"); | ||
650 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
651 | GOTO_ERROR_ON(res != 0, "MAC next tpl data"); | ||
652 | } | 744 | } |
653 | GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size"); | ||
654 | memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN); | ||
655 | 745 | ||
656 | /* Fetch the vendor specific tuples. */ | 746 | /* Fetch the vendor specific tuples. */ |
657 | memset(&tuple, 0, sizeof(tuple)); | 747 | res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS, |
658 | tuple.DesiredTuple = SSB_PCMCIA_CIS; | 748 | ssb_pcmcia_do_get_invariants, sprom); |
659 | tuple.TupleData = buf; | 749 | if ((res == 0) || (res == -ENOSPC)) |
660 | tuple.TupleDataMax = sizeof(buf); | 750 | return 0; |
661 | res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); | ||
662 | GOTO_ERROR_ON(res != 0, "VEN first tpl"); | ||
663 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
664 | GOTO_ERROR_ON(res != 0, "VEN first tpl data"); | ||
665 | while (1) { | ||
666 | GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1"); | ||
667 | switch (tuple.TupleData[0]) { | ||
668 | case SSB_PCMCIA_CIS_ID: | ||
669 | GOTO_ERROR_ON((tuple.TupleDataLen != 5) && | ||
670 | (tuple.TupleDataLen != 7), | ||
671 | "id tpl size"); | ||
672 | bi->vendor = tuple.TupleData[1] | | ||
673 | ((u16)tuple.TupleData[2] << 8); | ||
674 | break; | ||
675 | case SSB_PCMCIA_CIS_BOARDREV: | ||
676 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
677 | "boardrev tpl size"); | ||
678 | sprom->board_rev = tuple.TupleData[1]; | ||
679 | break; | ||
680 | case SSB_PCMCIA_CIS_PA: | ||
681 | GOTO_ERROR_ON((tuple.TupleDataLen != 9) && | ||
682 | (tuple.TupleDataLen != 10), | ||
683 | "pa tpl size"); | ||
684 | sprom->pa0b0 = tuple.TupleData[1] | | ||
685 | ((u16)tuple.TupleData[2] << 8); | ||
686 | sprom->pa0b1 = tuple.TupleData[3] | | ||
687 | ((u16)tuple.TupleData[4] << 8); | ||
688 | sprom->pa0b2 = tuple.TupleData[5] | | ||
689 | ((u16)tuple.TupleData[6] << 8); | ||
690 | sprom->itssi_a = tuple.TupleData[7]; | ||
691 | sprom->itssi_bg = tuple.TupleData[7]; | ||
692 | sprom->maxpwr_a = tuple.TupleData[8]; | ||
693 | sprom->maxpwr_bg = tuple.TupleData[8]; | ||
694 | break; | ||
695 | case SSB_PCMCIA_CIS_OEMNAME: | ||
696 | /* We ignore this. */ | ||
697 | break; | ||
698 | case SSB_PCMCIA_CIS_CCODE: | ||
699 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
700 | "ccode tpl size"); | ||
701 | sprom->country_code = tuple.TupleData[1]; | ||
702 | break; | ||
703 | case SSB_PCMCIA_CIS_ANTENNA: | ||
704 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
705 | "ant tpl size"); | ||
706 | sprom->ant_available_a = tuple.TupleData[1]; | ||
707 | sprom->ant_available_bg = tuple.TupleData[1]; | ||
708 | break; | ||
709 | case SSB_PCMCIA_CIS_ANTGAIN: | ||
710 | GOTO_ERROR_ON(tuple.TupleDataLen != 2, | ||
711 | "antg tpl size"); | ||
712 | sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1]; | ||
713 | sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1]; | ||
714 | sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1]; | ||
715 | sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1]; | ||
716 | sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1]; | ||
717 | sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1]; | ||
718 | sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1]; | ||
719 | sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; | ||
720 | break; | ||
721 | case SSB_PCMCIA_CIS_BFLAGS: | ||
722 | GOTO_ERROR_ON((tuple.TupleDataLen != 3) && | ||
723 | (tuple.TupleDataLen != 5), | ||
724 | "bfl tpl size"); | ||
725 | sprom->boardflags_lo = tuple.TupleData[1] | | ||
726 | ((u16)tuple.TupleData[2] << 8); | ||
727 | break; | ||
728 | case SSB_PCMCIA_CIS_LEDS: | ||
729 | GOTO_ERROR_ON(tuple.TupleDataLen != 5, | ||
730 | "leds tpl size"); | ||
731 | sprom->gpio0 = tuple.TupleData[1]; | ||
732 | sprom->gpio1 = tuple.TupleData[2]; | ||
733 | sprom->gpio2 = tuple.TupleData[3]; | ||
734 | sprom->gpio3 = tuple.TupleData[4]; | ||
735 | break; | ||
736 | } | ||
737 | res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); | ||
738 | if (res == -ENOSPC) | ||
739 | break; | ||
740 | GOTO_ERROR_ON(res != 0, "VEN next tpl"); | ||
741 | res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); | ||
742 | GOTO_ERROR_ON(res != 0, "VEN next tpl data"); | ||
743 | } | ||
744 | 751 | ||
745 | return 0; | ||
746 | error: | ||
747 | ssb_printk(KERN_ERR PFX | 752 | ssb_printk(KERN_ERR PFX |
748 | "PCMCIA: Failed to fetch device invariants: %s\n", | 753 | "PCMCIA: Failed to fetch device invariants\n"); |
749 | error_description); | ||
750 | return -ENODEV; | 754 | return -ENODEV; |
751 | } | 755 | } |
752 | 756 | ||