diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-01-10 19:14:18 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:00:24 -0500 |
commit | 6917f506a03b6bd7389683e8a8e08a1ad977b33e (patch) | |
tree | 1a5ed1755ae86666eea587a2c942984f9444932c /drivers/net/wireless/p54 | |
parent | 83cf1b6edba6bde87c8cf852b182d44b12ae7f88 (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.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.h | 72 |
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 | ||
133 | struct p54_iq_autocal_entry { | ||
134 | __le16 iq_param[4]; | ||
135 | } __attribute__ ((packed)); | ||
136 | |||
128 | struct pda_iq_autocal_entry { | 137 | struct 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 | ||
133 | struct pda_channel_output_limit { | 142 | struct 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 | */ | ||
201 | struct p54_channel_output_limit_longbow { | ||
202 | __le16 rf_power_points[12]; | ||
203 | } __attribute__ ((packed)); | ||
204 | |||
205 | struct 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 | |||
189 | struct pda_custom_wrapper { | 213 | struct 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 | ||
447 | struct p54_scan { | 480 | struct 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 | |||
487 | struct 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 { | 501 | struct 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 | 507 | union 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 | |||
512 | struct p54_scan_tail_rate { | ||
513 | __le32 basic_rate_mask; | ||
514 | u8 rts_rates[8]; | ||
515 | } __attribute__ ((packed)); | ||
476 | 516 | ||
477 | struct p54_led { | 517 | struct p54_led { |
478 | __le16 mode; | 518 | __le16 mode; |