aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2009-01-10 19:14:18 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-29 16:00:24 -0500
commit6917f506a03b6bd7389683e8a8e08a1ad977b33e (patch)
tree1a5ed1755ae86666eea587a2c942984f9444932c /drivers/net/wireless/p54
parent83cf1b6edba6bde87c8cf852b182d44b12ae7f88 (diff)
p54: longbow frontend support
This patch adds support for longbow RF chip. Signed-off-by: Christian Lamparter <chunkeey@web.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r--drivers/net/wireless/p54/p54common.c141
-rw-r--r--drivers/net/wireless/p54/p54common.h72
2 files changed, 160 insertions, 53 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index ec0d109c0095..9fc0c9efe701 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -651,7 +651,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
651 } 651 }
652 652
653 priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; 653 priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
654 if (priv->rxhw == 4) 654 if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW)
655 p54_init_xbow_synth(dev); 655 p54_init_xbow_synth(dev);
656 if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) 656 if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
657 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; 657 dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
@@ -704,7 +704,14 @@ static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
704 struct p54_common *priv = dev->priv; 704 struct p54_common *priv = dev->priv;
705 int band = dev->conf.channel->band; 705 int band = dev->conf.channel->band;
706 706
707 return ((rssi * priv->rssical_db[band].mul) / 64 + 707 if (priv->rxhw != PDR_SYNTH_FRONTEND_LONGBOW)
708 return ((rssi * priv->rssical_db[band].mul) / 64 +
709 priv->rssical_db[band].add) / 4;
710 else
711 /*
712 * TODO: find the correct formula
713 */
714 return ((rssi * priv->rssical_db[band].mul) / 64 +
708 priv->rssical_db[band].add) / 4; 715 priv->rssical_db[band].add) / 4;
709} 716}
710 717
@@ -1612,8 +1619,13 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
1612 memset(txhdr->durations, 0, sizeof(txhdr->durations)); 1619 memset(txhdr->durations, 0, sizeof(txhdr->durations));
1613 txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? 1620 txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ?
1614 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; 1621 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask;
1615 txhdr->output_power = priv->output_power; 1622 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
1616 txhdr->cts_rate = cts_rate; 1623 txhdr->longbow.cts_rate = cts_rate;
1624 txhdr->longbow.output_power = cpu_to_le16(priv->output_power);
1625 } else {
1626 txhdr->normal.output_power = priv->output_power;
1627 txhdr->normal.cts_rate = cts_rate;
1628 }
1617 if (padding) 1629 if (padding)
1618 txhdr->align[0] = padding; 1630 txhdr->align[0] = padding;
1619 1631
@@ -1715,47 +1727,77 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
1715{ 1727{
1716 struct p54_common *priv = dev->priv; 1728 struct p54_common *priv = dev->priv;
1717 struct sk_buff *skb; 1729 struct sk_buff *skb;
1718 struct p54_scan *chan; 1730 struct p54_hdr *hdr;
1731 struct p54_scan_head *head;
1732 struct p54_iq_autocal_entry *iq_autocal;
1733 union p54_scan_body_union *body;
1734 struct p54_scan_tail_rate *rate;
1735 struct pda_rssi_cal_entry *rssi;
1719 unsigned int i; 1736 unsigned int i;
1720 void *entry; 1737 void *entry;
1721 int band = dev->conf.channel->band; 1738 int band = dev->conf.channel->band;
1722 __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); 1739 __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
1723 1740
1724 skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan), 1741 skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
1742 2 + sizeof(*iq_autocal) + sizeof(*body) +
1743 sizeof(*rate) + 2 * sizeof(*rssi),
1725 P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); 1744 P54_CONTROL_TYPE_SCAN, GFP_ATOMIC);
1726 if (!skb) 1745 if (!skb)
1727 return -ENOMEM; 1746 return -ENOMEM;
1728 1747
1729 chan = (struct p54_scan *) skb_put(skb, sizeof(*chan)); 1748 head = (struct p54_scan_head *) skb_put(skb, sizeof(*head));
1730 memset(chan->scan_params, 0, sizeof(chan->scan_params)); 1749 memset(head->scan_params, 0, sizeof(head->scan_params));
1731 chan->mode = cpu_to_le16(mode); 1750 head->mode = cpu_to_le16(mode);
1732 chan->dwell = cpu_to_le16(dwell); 1751 head->dwell = cpu_to_le16(dwell);
1752 head->freq = freq;
1733 1753
1754 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
1755 __le16 *pa_power_points = (__le16 *) skb_put(skb, 2);
1756 *pa_power_points = cpu_to_le16(0x0c);
1757 }
1758
1759 iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal));
1734 for (i = 0; i < priv->iq_autocal_len; i++) { 1760 for (i = 0; i < priv->iq_autocal_len; i++) {
1735 if (priv->iq_autocal[i].freq != freq) 1761 if (priv->iq_autocal[i].freq != freq)
1736 continue; 1762 continue;
1737 1763
1738 memcpy(&chan->iq_autocal, &priv->iq_autocal[i], 1764 memcpy(iq_autocal, &priv->iq_autocal[i].params,
1739 sizeof(*priv->iq_autocal)); 1765 sizeof(struct p54_iq_autocal_entry));
1740 break; 1766 break;
1741 } 1767 }
1742 if (i == priv->iq_autocal_len) 1768 if (i == priv->iq_autocal_len)
1743 goto err; 1769 goto err;
1744 1770
1771 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW)
1772 body = (void *) skb_put(skb, sizeof(body->longbow));
1773 else
1774 body = (void *) skb_put(skb, sizeof(body->normal));
1775
1745 for (i = 0; i < priv->output_limit->entries; i++) { 1776 for (i = 0; i < priv->output_limit->entries; i++) {
1746 struct pda_channel_output_limit *limits;
1747 __le16 *entry_freq = (void *) (priv->output_limit->data + 1777 __le16 *entry_freq = (void *) (priv->output_limit->data +
1748 priv->output_limit->entry_size * i); 1778 priv->output_limit->entry_size * i);
1749 1779
1750 if (*entry_freq != freq) 1780 if (*entry_freq != freq)
1751 continue; 1781 continue;
1752 1782
1753 limits = (void *) entry_freq; 1783 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
1754 chan->val_barker = 0x38; 1784 memcpy(&body->longbow.power_limits,
1755 chan->val_bpsk = chan->dup_bpsk = limits->val_bpsk; 1785 (void *) entry_freq + sizeof(__le16),
1756 chan->val_qpsk = chan->dup_qpsk = limits->val_qpsk; 1786 priv->output_limit->entry_size);
1757 chan->val_16qam = chan->dup_16qam = limits->val_16qam; 1787 } else {
1758 chan->val_64qam = chan->dup_64qam = limits->val_64qam; 1788 struct pda_channel_output_limit *limits =
1789 (void *) entry_freq;
1790
1791 body->normal.val_barker = 0x38;
1792 body->normal.val_bpsk = body->normal.dup_bpsk =
1793 limits->val_bpsk;
1794 body->normal.val_qpsk = body->normal.dup_qpsk =
1795 limits->val_qpsk;
1796 body->normal.val_16qam = body->normal.dup_16qam =
1797 limits->val_16qam;
1798 body->normal.val_64qam = body->normal.dup_64qam =
1799 limits->val_64qam;
1800 }
1759 break; 1801 break;
1760 } 1802 }
1761 if (i == priv->output_limit->entries) 1803 if (i == priv->output_limit->entries)
@@ -1763,34 +1805,59 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
1763 1805
1764 entry = (void *)(priv->curve_data->data + priv->curve_data->offset); 1806 entry = (void *)(priv->curve_data->data + priv->curve_data->offset);
1765 for (i = 0; i < priv->curve_data->entries; i++) { 1807 for (i = 0; i < priv->curve_data->entries; i++) {
1766 struct pda_pa_curve_data *curve_data;
1767 if (*((__le16 *)entry) != freq) { 1808 if (*((__le16 *)entry) != freq) {
1768 entry += priv->curve_data->entry_size; 1809 entry += priv->curve_data->entry_size;
1769 continue; 1810 continue;
1770 } 1811 }
1771 1812
1772 entry += sizeof(__le16); 1813 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
1773 chan->pa_points_per_curve = 8; 1814 memcpy(&body->longbow.curve_data,
1774 memset(chan->curve_data, 0, sizeof(*chan->curve_data)); 1815 (void *) entry + sizeof(__le16),
1775 curve_data = (void *) priv->curve_data->data; 1816 priv->curve_data->entry_size);
1776 1817 } else {
1777 memcpy(chan->curve_data, entry, 1818 struct p54_scan_body *chan = &body->normal;
1778 sizeof(struct p54_pa_curve_data_sample) * 1819 struct pda_pa_curve_data *curve_data =
1779 min_t(u8, 8, curve_data->points_per_channel)); 1820 (void *) priv->curve_data->data;
1821
1822 entry += sizeof(__le16);
1823 chan->pa_points_per_curve = 8;
1824 memset(chan->curve_data, 0, sizeof(*chan->curve_data));
1825 memcpy(chan->curve_data, entry,
1826 sizeof(struct p54_pa_curve_data_sample) *
1827 min((u8)8, curve_data->points_per_channel));
1828 }
1780 break; 1829 break;
1781 } 1830 }
1782 if (i == priv->curve_data->entries) 1831 if (i == priv->curve_data->entries)
1783 goto err; 1832 goto err;
1784 1833
1785 if (priv->fw_var < 0x500) { 1834 if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) {
1786 chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); 1835 rate = (void *) skb_put(skb, sizeof(*rate));
1787 chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add); 1836 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
1788 } else { 1837 for (i = 0; i < sizeof(rate->rts_rates); i++)
1789 chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); 1838 rate->rts_rates[i] = i;
1790 chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add);
1791 chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
1792 memset(chan->v2.rts_rates, 0, 8);
1793 } 1839 }
1840
1841 rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
1842 rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
1843 rssi->add = cpu_to_le16(priv->rssical_db[band].add);
1844 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
1845 /* Longbow frontend needs ever more */
1846 rssi = (void *) skb_put(skb, sizeof(*rssi));
1847 rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
1848 rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
1849 }
1850
1851 if (priv->fw_var >= 0x509) {
1852 rate = (void *) skb_put(skb, sizeof(*rate));
1853 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
1854 for (i = 0; i < sizeof(rate->rts_rates); i++)
1855 rate->rts_rates[i] = i;
1856 }
1857
1858 hdr = (struct p54_hdr *) skb->data;
1859 hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
1860
1794 priv->tx(dev, skb); 1861 priv->tx(dev, skb);
1795 return 0; 1862 return 0;
1796 1863
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index d9aa255b4717..def23b1f49ec 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -26,6 +26,11 @@ struct bootrec {
26} __attribute__((packed)); 26} __attribute__((packed));
27 27
28#define PDR_SYNTH_FRONTEND_MASK 0x0007 28#define PDR_SYNTH_FRONTEND_MASK 0x0007
29#define PDR_SYNTH_FRONTEND_DUETTE3 0x0001
30#define PDR_SYNTH_FRONTEND_DUETTE2 0x0002
31#define PDR_SYNTH_FRONTEND_FRISBEE 0x0003
32#define PDR_SYNTH_FRONTEND_XBOW 0x0004
33#define PDR_SYNTH_FRONTEND_LONGBOW 0x0005
29#define PDR_SYNTH_IQ_CAL_MASK 0x0018 34#define PDR_SYNTH_IQ_CAL_MASK 0x0018
30#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000 35#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000
31#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008 36#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008
@@ -125,9 +130,13 @@ struct eeprom_pda_wrap {
125 u8 data[0]; 130 u8 data[0];
126} __attribute__ ((packed)); 131} __attribute__ ((packed));
127 132
133struct p54_iq_autocal_entry {
134 __le16 iq_param[4];
135} __attribute__ ((packed));
136
128struct pda_iq_autocal_entry { 137struct pda_iq_autocal_entry {
129 __le16 freq; 138 __le16 freq;
130 __le16 iq_param[4]; 139 struct p54_iq_autocal_entry params;
131} __attribute__ ((packed)); 140} __attribute__ ((packed));
132 141
133struct pda_channel_output_limit { 142struct pda_channel_output_limit {
@@ -186,6 +195,21 @@ struct pda_country {
186 u8 flags; 195 u8 flags;
187} __attribute__ ((packed)); 196} __attribute__ ((packed));
188 197
198/*
199 * Warning: Longbow's structures are bogus.
200 */
201struct p54_channel_output_limit_longbow {
202 __le16 rf_power_points[12];
203} __attribute__ ((packed));
204
205struct p54_pa_curve_data_sample_longbow {
206 __le16 rf_power;
207 __le16 pa_detector;
208 struct {
209 __le16 data[4];
210 } points[3] __attribute__ ((packed));
211} __attribute__ ((packed));
212
189struct pda_custom_wrapper { 213struct pda_custom_wrapper {
190 __le16 entries; 214 __le16 entries;
191 __le16 entry_size; 215 __le16 entry_size;
@@ -381,9 +405,18 @@ struct p54_tx_data {
381 u8 backlog; 405 u8 backlog;
382 __le16 durations[4]; 406 __le16 durations[4];
383 u8 tx_antenna; 407 u8 tx_antenna;
384 u8 output_power; 408 union {
385 u8 cts_rate; 409 struct {
386 u8 unalloc2[3]; 410 u8 cts_rate;
411 __le16 output_power;
412 } __attribute__((packed)) longbow;
413 struct {
414 u8 output_power;
415 u8 cts_rate;
416 u8 unalloc;
417 } __attribute__ ((packed)) normal;
418 } __attribute__ ((packed));
419 u8 unalloc2[2];
387 u8 align[0]; 420 u8 align[0];
388} __attribute__ ((packed)); 421} __attribute__ ((packed));
389 422
@@ -444,11 +477,14 @@ struct p54_setup_mac {
444#define P54_SCAN_ACTIVE BIT(2) 477#define P54_SCAN_ACTIVE BIT(2)
445#define P54_SCAN_FILTER BIT(3) 478#define P54_SCAN_FILTER BIT(3)
446 479
447struct p54_scan { 480struct p54_scan_head {
448 __le16 mode; 481 __le16 mode;
449 __le16 dwell; 482 __le16 dwell;
450 u8 scan_params[20]; 483 u8 scan_params[20];
451 struct pda_iq_autocal_entry iq_autocal; 484 __le16 freq;
485} __attribute__ ((packed));
486
487struct p54_scan_body {
452 u8 pa_points_per_curve; 488 u8 pa_points_per_curve;
453 u8 val_barker; 489 u8 val_barker;
454 u8 val_bpsk; 490 u8 val_bpsk;
@@ -460,19 +496,23 @@ struct p54_scan {
460 u8 dup_qpsk; 496 u8 dup_qpsk;
461 u8 dup_16qam; 497 u8 dup_16qam;
462 u8 dup_64qam; 498 u8 dup_64qam;
463 union { 499} __attribute__ ((packed));
464 struct pda_rssi_cal_entry v1_rssi;
465 500
466 struct { 501struct p54_scan_body_longbow {
467 __le32 basic_rate_mask; 502 struct p54_channel_output_limit_longbow power_limits;
468 u8 rts_rates[8]; 503 struct p54_pa_curve_data_sample_longbow curve_data[8];
469 struct pda_rssi_cal_entry rssi; 504 __le16 unkn[6]; /* maybe more power_limits or rate_mask */
470 } v2 __attribute__ ((packed));
471 } __attribute__ ((packed));
472} __attribute__ ((packed)); 505} __attribute__ ((packed));
473 506
474#define P54_SCAN_V1_LEN 0x70 507union p54_scan_body_union {
475#define P54_SCAN_V2_LEN 0x7c 508 struct p54_scan_body normal;
509 struct p54_scan_body_longbow longbow;
510} __attribute__ ((packed));
511
512struct p54_scan_tail_rate {
513 __le32 basic_rate_mask;
514 u8 rts_rates[8];
515} __attribute__ ((packed));
476 516
477struct p54_led { 517struct p54_led {
478 __le16 mode; 518 __le16 mode;