aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/pcmcia.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2009-10-18 17:56:41 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2009-11-08 12:23:09 -0500
commit37ace3d4131ae80f370eb1230fa7db2b3eedf17c (patch)
tree85b2744a8f6a9989498638347eeb0994dd9f5426 /drivers/ssb/pcmcia.c
parentdddfbd824b96a25da0b2f1cf35c0be33ef2422fe (diff)
pcmcia: convert ssb pcmcia driver to use new CIS helpers
SSB is a prime example of how to make use of the new CIS helpers. CC: Michael Buesch <mb@bu3sch.de> Acked-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/ssb/pcmcia.c')
-rw-r--r--drivers/ssb/pcmcia.c232
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
620int ssb_pcmcia_get_invariants(struct ssb_bus *bus, 620static 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
636static 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
718error:
719 ssb_printk(KERN_ERR PFX
720 "PCMCIA: Failed to fetch device invariants: %s\n",
721 error_description);
722 return -ENODEV;
723}
724
725
726int 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;
746error:
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