diff options
author | David Kilroy <kilroyd@googlemail.com> | 2009-02-04 18:05:55 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-13 13:44:31 -0500 |
commit | 712a4342a0d89e855a03ba06fb11f7eb29456d45 (patch) | |
tree | e5b500f5e4e9f4b1e065009d7de2e19fba932ef5 /drivers/net/wireless/orinoco/main.c | |
parent | 5865d015cf85c619a51f8be93d44ec932bc90038 (diff) |
orinoco: Move hardware functions into separate file
No functional change.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco/main.c')
-rw-r--r-- | drivers/net/wireless/orinoco/main.c | 583 |
1 files changed, 1 insertions, 582 deletions
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 3e20df7b6570..a340c7d75dd1 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
@@ -91,6 +91,7 @@ | |||
91 | 91 | ||
92 | #include "hermes_rid.h" | 92 | #include "hermes_rid.h" |
93 | #include "hermes_dld.h" | 93 | #include "hermes_dld.h" |
94 | #include "hw.h" | ||
94 | #include "scan.h" | 95 | #include "scan.h" |
95 | #include "mic.h" | 96 | #include "mic.h" |
96 | #include "fw.h" | 97 | #include "fw.h" |
@@ -151,15 +152,11 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | |||
151 | #define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) | 152 | #define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) |
152 | 153 | ||
153 | #define SYMBOL_MAX_VER_LEN (14) | 154 | #define SYMBOL_MAX_VER_LEN (14) |
154 | #define USER_BAP 0 | ||
155 | #define IRQ_BAP 1 | ||
156 | #define MAX_IRQLOOPS_PER_IRQ 10 | 155 | #define MAX_IRQLOOPS_PER_IRQ 10 |
157 | #define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of | 156 | #define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of |
158 | * how many events the | 157 | * how many events the |
159 | * device could | 158 | * device could |
160 | * legitimately generate */ | 159 | * legitimately generate */ |
161 | #define SMALL_KEY_SIZE 5 | ||
162 | #define LARGE_KEY_SIZE 13 | ||
163 | #define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */ | 160 | #define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */ |
164 | 161 | ||
165 | #define DUMMY_FID 0xFFFF | 162 | #define DUMMY_FID 0xFFFF |
@@ -179,31 +176,6 @@ static const struct iw_handler_def orinoco_handler_def; | |||
179 | static const struct ethtool_ops orinoco_ethtool_ops; | 176 | static const struct ethtool_ops orinoco_ethtool_ops; |
180 | 177 | ||
181 | /********************************************************************/ | 178 | /********************************************************************/ |
182 | /* Data tables */ | ||
183 | /********************************************************************/ | ||
184 | |||
185 | #define NUM_CHANNELS 14 | ||
186 | |||
187 | /* This tables gives the actual meanings of the bitrate IDs returned | ||
188 | * by the firmware. */ | ||
189 | static struct { | ||
190 | int bitrate; /* in 100s of kilobits */ | ||
191 | int automatic; | ||
192 | u16 agere_txratectrl; | ||
193 | u16 intersil_txratectrl; | ||
194 | } bitrate_table[] = { | ||
195 | {110, 1, 3, 15}, /* Entry 0 is the default */ | ||
196 | {10, 0, 1, 1}, | ||
197 | {10, 1, 1, 1}, | ||
198 | {20, 0, 2, 2}, | ||
199 | {20, 1, 6, 3}, | ||
200 | {55, 0, 4, 4}, | ||
201 | {55, 1, 7, 7}, | ||
202 | {110, 0, 5, 8}, | ||
203 | }; | ||
204 | #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table) | ||
205 | |||
206 | /********************************************************************/ | ||
207 | /* Data types */ | 179 | /* Data types */ |
208 | /********************************************************************/ | 180 | /********************************************************************/ |
209 | 181 | ||
@@ -282,33 +254,6 @@ static inline void set_port_type(struct orinoco_private *priv) | |||
282 | } | 254 | } |
283 | } | 255 | } |
284 | 256 | ||
285 | static int orinoco_get_bitratemode(int bitrate, int automatic) | ||
286 | { | ||
287 | int ratemode = -1; | ||
288 | int i; | ||
289 | |||
290 | if ((bitrate != 10) && (bitrate != 20) && | ||
291 | (bitrate != 55) && (bitrate != 110)) | ||
292 | return ratemode; | ||
293 | |||
294 | for (i = 0; i < BITRATE_TABLE_SIZE; i++) { | ||
295 | if ((bitrate_table[i].bitrate == bitrate) && | ||
296 | (bitrate_table[i].automatic == automatic)) { | ||
297 | ratemode = i; | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | return ratemode; | ||
302 | } | ||
303 | |||
304 | static void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic) | ||
305 | { | ||
306 | BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE)); | ||
307 | |||
308 | *bitrate = bitrate_table[ratemode].bitrate * 100000; | ||
309 | *automatic = bitrate_table[ratemode].automatic; | ||
310 | } | ||
311 | |||
312 | static inline u8 *orinoco_get_ie(u8 *data, size_t len, | 257 | static inline u8 *orinoco_get_ie(u8 *data, size_t len, |
313 | enum ieee80211_eid eid) | 258 | enum ieee80211_eid eid) |
314 | { | 259 | { |
@@ -933,25 +878,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, | |||
933 | stats->rx_dropped++; | 878 | stats->rx_dropped++; |
934 | } | 879 | } |
935 | 880 | ||
936 | /* Get tsc from the firmware */ | ||
937 | static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, | ||
938 | u8 *tsc) | ||
939 | { | ||
940 | hermes_t *hw = &priv->hw; | ||
941 | int err = 0; | ||
942 | u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; | ||
943 | |||
944 | if ((key < 0) || (key > 4)) | ||
945 | return -EINVAL; | ||
946 | |||
947 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, | ||
948 | sizeof(tsc_arr), NULL, &tsc_arr); | ||
949 | if (!err) | ||
950 | memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0])); | ||
951 | |||
952 | return err; | ||
953 | } | ||
954 | |||
955 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) | 881 | static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) |
956 | { | 882 | { |
957 | struct orinoco_private *priv = netdev_priv(dev); | 883 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -1790,334 +1716,6 @@ int orinoco_reinit_firmware(struct net_device *dev) | |||
1790 | } | 1716 | } |
1791 | EXPORT_SYMBOL(orinoco_reinit_firmware); | 1717 | EXPORT_SYMBOL(orinoco_reinit_firmware); |
1792 | 1718 | ||
1793 | static int __orinoco_hw_set_bitrate(struct orinoco_private *priv) | ||
1794 | { | ||
1795 | hermes_t *hw = &priv->hw; | ||
1796 | int ratemode = priv->bitratemode; | ||
1797 | int err = 0; | ||
1798 | |||
1799 | if (ratemode >= BITRATE_TABLE_SIZE) { | ||
1800 | printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n", | ||
1801 | priv->ndev->name, ratemode); | ||
1802 | return -EINVAL; | ||
1803 | } | ||
1804 | |||
1805 | switch (priv->firmware_type) { | ||
1806 | case FIRMWARE_TYPE_AGERE: | ||
1807 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1808 | HERMES_RID_CNFTXRATECONTROL, | ||
1809 | bitrate_table[ratemode].agere_txratectrl); | ||
1810 | break; | ||
1811 | case FIRMWARE_TYPE_INTERSIL: | ||
1812 | case FIRMWARE_TYPE_SYMBOL: | ||
1813 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1814 | HERMES_RID_CNFTXRATECONTROL, | ||
1815 | bitrate_table[ratemode].intersil_txratectrl); | ||
1816 | break; | ||
1817 | default: | ||
1818 | BUG(); | ||
1819 | } | ||
1820 | |||
1821 | return err; | ||
1822 | } | ||
1823 | |||
1824 | static int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, | ||
1825 | int *bitrate) | ||
1826 | { | ||
1827 | hermes_t *hw = &priv->hw; | ||
1828 | int i; | ||
1829 | int err = 0; | ||
1830 | u16 val; | ||
1831 | |||
1832 | err = hermes_read_wordrec(hw, USER_BAP, | ||
1833 | HERMES_RID_CURRENTTXRATE, &val); | ||
1834 | if (err) | ||
1835 | return err; | ||
1836 | |||
1837 | switch (priv->firmware_type) { | ||
1838 | case FIRMWARE_TYPE_AGERE: /* Lucent style rate */ | ||
1839 | /* Note : in Lucent firmware, the return value of | ||
1840 | * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s, | ||
1841 | * and therefore is totally different from the | ||
1842 | * encoding of HERMES_RID_CNFTXRATECONTROL. | ||
1843 | * Don't forget that 6Mb/s is really 5.5Mb/s */ | ||
1844 | if (val == 6) | ||
1845 | *bitrate = 5500000; | ||
1846 | else | ||
1847 | *bitrate = val * 1000000; | ||
1848 | break; | ||
1849 | case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ | ||
1850 | case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ | ||
1851 | for (i = 0; i < BITRATE_TABLE_SIZE; i++) | ||
1852 | if (bitrate_table[i].intersil_txratectrl == val) | ||
1853 | break; | ||
1854 | |||
1855 | if (i >= BITRATE_TABLE_SIZE) | ||
1856 | printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n", | ||
1857 | priv->ndev->name, val); | ||
1858 | |||
1859 | *bitrate = bitrate_table[i].bitrate * 100000; | ||
1860 | break; | ||
1861 | default: | ||
1862 | BUG(); | ||
1863 | } | ||
1864 | |||
1865 | return err; | ||
1866 | } | ||
1867 | |||
1868 | /* Set fixed AP address */ | ||
1869 | static int __orinoco_hw_set_wap(struct orinoco_private *priv) | ||
1870 | { | ||
1871 | int roaming_flag; | ||
1872 | int err = 0; | ||
1873 | hermes_t *hw = &priv->hw; | ||
1874 | |||
1875 | switch (priv->firmware_type) { | ||
1876 | case FIRMWARE_TYPE_AGERE: | ||
1877 | /* not supported */ | ||
1878 | break; | ||
1879 | case FIRMWARE_TYPE_INTERSIL: | ||
1880 | if (priv->bssid_fixed) | ||
1881 | roaming_flag = 2; | ||
1882 | else | ||
1883 | roaming_flag = 1; | ||
1884 | |||
1885 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1886 | HERMES_RID_CNFROAMINGMODE, | ||
1887 | roaming_flag); | ||
1888 | break; | ||
1889 | case FIRMWARE_TYPE_SYMBOL: | ||
1890 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
1891 | HERMES_RID_CNFMANDATORYBSSID_SYMBOL, | ||
1892 | &priv->desired_bssid); | ||
1893 | break; | ||
1894 | } | ||
1895 | return err; | ||
1896 | } | ||
1897 | |||
1898 | /* Change the WEP keys and/or the current keys. Can be called | ||
1899 | * either from __orinoco_hw_setup_enc() or directly from | ||
1900 | * orinoco_ioctl_setiwencode(). In the later case the association | ||
1901 | * with the AP is not broken (if the firmware can handle it), | ||
1902 | * which is needed for 802.1x implementations. */ | ||
1903 | static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv) | ||
1904 | { | ||
1905 | hermes_t *hw = &priv->hw; | ||
1906 | int err = 0; | ||
1907 | |||
1908 | switch (priv->firmware_type) { | ||
1909 | case FIRMWARE_TYPE_AGERE: | ||
1910 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
1911 | HERMES_RID_CNFWEPKEYS_AGERE, | ||
1912 | &priv->keys); | ||
1913 | if (err) | ||
1914 | return err; | ||
1915 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1916 | HERMES_RID_CNFTXKEY_AGERE, | ||
1917 | priv->tx_key); | ||
1918 | if (err) | ||
1919 | return err; | ||
1920 | break; | ||
1921 | case FIRMWARE_TYPE_INTERSIL: | ||
1922 | case FIRMWARE_TYPE_SYMBOL: | ||
1923 | { | ||
1924 | int keylen; | ||
1925 | int i; | ||
1926 | |||
1927 | /* Force uniform key length to work around | ||
1928 | * firmware bugs */ | ||
1929 | keylen = le16_to_cpu(priv->keys[priv->tx_key].len); | ||
1930 | |||
1931 | if (keylen > LARGE_KEY_SIZE) { | ||
1932 | printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", | ||
1933 | priv->ndev->name, priv->tx_key, keylen); | ||
1934 | return -E2BIG; | ||
1935 | } | ||
1936 | |||
1937 | /* Write all 4 keys */ | ||
1938 | for (i = 0; i < ORINOCO_MAX_KEYS; i++) { | ||
1939 | err = hermes_write_ltv(hw, USER_BAP, | ||
1940 | HERMES_RID_CNFDEFAULTKEY0 + i, | ||
1941 | HERMES_BYTES_TO_RECLEN(keylen), | ||
1942 | priv->keys[i].data); | ||
1943 | if (err) | ||
1944 | return err; | ||
1945 | } | ||
1946 | |||
1947 | /* Write the index of the key used in transmission */ | ||
1948 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1949 | HERMES_RID_CNFWEPDEFAULTKEYID, | ||
1950 | priv->tx_key); | ||
1951 | if (err) | ||
1952 | return err; | ||
1953 | } | ||
1954 | break; | ||
1955 | } | ||
1956 | |||
1957 | return 0; | ||
1958 | } | ||
1959 | |||
1960 | static int __orinoco_hw_setup_enc(struct orinoco_private *priv) | ||
1961 | { | ||
1962 | hermes_t *hw = &priv->hw; | ||
1963 | int err = 0; | ||
1964 | int master_wep_flag; | ||
1965 | int auth_flag; | ||
1966 | int enc_flag; | ||
1967 | |||
1968 | /* Setup WEP keys for WEP and WPA */ | ||
1969 | if (priv->encode_alg) | ||
1970 | __orinoco_hw_setup_wepkeys(priv); | ||
1971 | |||
1972 | if (priv->wep_restrict) | ||
1973 | auth_flag = HERMES_AUTH_SHARED_KEY; | ||
1974 | else | ||
1975 | auth_flag = HERMES_AUTH_OPEN; | ||
1976 | |||
1977 | if (priv->wpa_enabled) | ||
1978 | enc_flag = 2; | ||
1979 | else if (priv->encode_alg == IW_ENCODE_ALG_WEP) | ||
1980 | enc_flag = 1; | ||
1981 | else | ||
1982 | enc_flag = 0; | ||
1983 | |||
1984 | switch (priv->firmware_type) { | ||
1985 | case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ | ||
1986 | if (priv->encode_alg == IW_ENCODE_ALG_WEP) { | ||
1987 | /* Enable the shared-key authentication. */ | ||
1988 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1989 | HERMES_RID_CNFAUTHENTICATION_AGERE, | ||
1990 | auth_flag); | ||
1991 | } | ||
1992 | err = hermes_write_wordrec(hw, USER_BAP, | ||
1993 | HERMES_RID_CNFWEPENABLED_AGERE, | ||
1994 | enc_flag); | ||
1995 | if (err) | ||
1996 | return err; | ||
1997 | |||
1998 | if (priv->has_wpa) { | ||
1999 | /* Set WPA key management */ | ||
2000 | err = hermes_write_wordrec(hw, USER_BAP, | ||
2001 | HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE, | ||
2002 | priv->key_mgmt); | ||
2003 | if (err) | ||
2004 | return err; | ||
2005 | } | ||
2006 | |||
2007 | break; | ||
2008 | |||
2009 | case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ | ||
2010 | case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ | ||
2011 | if (priv->encode_alg == IW_ENCODE_ALG_WEP) { | ||
2012 | if (priv->wep_restrict || | ||
2013 | (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)) | ||
2014 | master_wep_flag = HERMES_WEP_PRIVACY_INVOKED | | ||
2015 | HERMES_WEP_EXCL_UNENCRYPTED; | ||
2016 | else | ||
2017 | master_wep_flag = HERMES_WEP_PRIVACY_INVOKED; | ||
2018 | |||
2019 | err = hermes_write_wordrec(hw, USER_BAP, | ||
2020 | HERMES_RID_CNFAUTHENTICATION, | ||
2021 | auth_flag); | ||
2022 | if (err) | ||
2023 | return err; | ||
2024 | } else | ||
2025 | master_wep_flag = 0; | ||
2026 | |||
2027 | if (priv->iw_mode == IW_MODE_MONITOR) | ||
2028 | master_wep_flag |= HERMES_WEP_HOST_DECRYPT; | ||
2029 | |||
2030 | /* Master WEP setting : on/off */ | ||
2031 | err = hermes_write_wordrec(hw, USER_BAP, | ||
2032 | HERMES_RID_CNFWEPFLAGS_INTERSIL, | ||
2033 | master_wep_flag); | ||
2034 | if (err) | ||
2035 | return err; | ||
2036 | |||
2037 | break; | ||
2038 | } | ||
2039 | |||
2040 | return 0; | ||
2041 | } | ||
2042 | |||
2043 | /* key must be 32 bytes, including the tx and rx MIC keys. | ||
2044 | * rsc must be 8 bytes | ||
2045 | * tsc must be 8 bytes or NULL | ||
2046 | */ | ||
2047 | static int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx, | ||
2048 | u8 *key, u8 *rsc, u8 *tsc) | ||
2049 | { | ||
2050 | struct { | ||
2051 | __le16 idx; | ||
2052 | u8 rsc[IW_ENCODE_SEQ_MAX_SIZE]; | ||
2053 | u8 key[TKIP_KEYLEN]; | ||
2054 | u8 tx_mic[MIC_KEYLEN]; | ||
2055 | u8 rx_mic[MIC_KEYLEN]; | ||
2056 | u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; | ||
2057 | } __attribute__ ((packed)) buf; | ||
2058 | int ret; | ||
2059 | int err; | ||
2060 | int k; | ||
2061 | u16 xmitting; | ||
2062 | |||
2063 | key_idx &= 0x3; | ||
2064 | |||
2065 | if (set_tx) | ||
2066 | key_idx |= 0x8000; | ||
2067 | |||
2068 | buf.idx = cpu_to_le16(key_idx); | ||
2069 | memcpy(buf.key, key, | ||
2070 | sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic)); | ||
2071 | |||
2072 | if (rsc == NULL) | ||
2073 | memset(buf.rsc, 0, sizeof(buf.rsc)); | ||
2074 | else | ||
2075 | memcpy(buf.rsc, rsc, sizeof(buf.rsc)); | ||
2076 | |||
2077 | if (tsc == NULL) { | ||
2078 | memset(buf.tsc, 0, sizeof(buf.tsc)); | ||
2079 | buf.tsc[4] = 0x10; | ||
2080 | } else { | ||
2081 | memcpy(buf.tsc, tsc, sizeof(buf.tsc)); | ||
2082 | } | ||
2083 | |||
2084 | /* Wait upto 100ms for tx queue to empty */ | ||
2085 | k = 100; | ||
2086 | do { | ||
2087 | k--; | ||
2088 | udelay(1000); | ||
2089 | ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY, | ||
2090 | &xmitting); | ||
2091 | if (ret) | ||
2092 | break; | ||
2093 | } while ((k > 0) && xmitting); | ||
2094 | |||
2095 | if (k == 0) | ||
2096 | ret = -ETIMEDOUT; | ||
2097 | |||
2098 | err = HERMES_WRITE_RECORD(hw, USER_BAP, | ||
2099 | HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE, | ||
2100 | &buf); | ||
2101 | |||
2102 | return ret ? ret : err; | ||
2103 | } | ||
2104 | |||
2105 | static int orinoco_clear_tkip_key(struct orinoco_private *priv, | ||
2106 | int key_idx) | ||
2107 | { | ||
2108 | hermes_t *hw = &priv->hw; | ||
2109 | int err; | ||
2110 | |||
2111 | memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx])); | ||
2112 | err = hermes_write_wordrec(hw, USER_BAP, | ||
2113 | HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE, | ||
2114 | key_idx); | ||
2115 | if (err) | ||
2116 | printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n", | ||
2117 | priv->ndev->name, err, key_idx); | ||
2118 | return err; | ||
2119 | } | ||
2120 | |||
2121 | static int __orinoco_program_rids(struct net_device *dev) | 1719 | static int __orinoco_program_rids(struct net_device *dev) |
2122 | { | 1720 | { |
2123 | struct orinoco_private *priv = netdev_priv(dev); | 1721 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -2347,59 +1945,6 @@ static int __orinoco_program_rids(struct net_device *dev) | |||
2347 | return 0; | 1945 | return 0; |
2348 | } | 1946 | } |
2349 | 1947 | ||
2350 | static int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, | ||
2351 | struct dev_addr_list *mc_list, | ||
2352 | int mc_count, int promisc) | ||
2353 | { | ||
2354 | hermes_t *hw = &priv->hw; | ||
2355 | int err = 0; | ||
2356 | |||
2357 | if (promisc != priv->promiscuous) { | ||
2358 | err = hermes_write_wordrec(hw, USER_BAP, | ||
2359 | HERMES_RID_CNFPROMISCUOUSMODE, | ||
2360 | promisc); | ||
2361 | if (err) { | ||
2362 | printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n", | ||
2363 | priv->ndev->name, err); | ||
2364 | } else | ||
2365 | priv->promiscuous = promisc; | ||
2366 | } | ||
2367 | |||
2368 | /* If we're not in promiscuous mode, then we need to set the | ||
2369 | * group address if either we want to multicast, or if we were | ||
2370 | * multicasting and want to stop */ | ||
2371 | if (!promisc && (mc_count || priv->mc_count)) { | ||
2372 | struct dev_mc_list *p = mc_list; | ||
2373 | struct hermes_multicast mclist; | ||
2374 | int i; | ||
2375 | |||
2376 | for (i = 0; i < mc_count; i++) { | ||
2377 | /* paranoia: is list shorter than mc_count? */ | ||
2378 | BUG_ON(!p); | ||
2379 | /* paranoia: bad address size in list? */ | ||
2380 | BUG_ON(p->dmi_addrlen != ETH_ALEN); | ||
2381 | |||
2382 | memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN); | ||
2383 | p = p->next; | ||
2384 | } | ||
2385 | |||
2386 | if (p) | ||
2387 | printk(KERN_WARNING "%s: Multicast list is " | ||
2388 | "longer than mc_count\n", priv->ndev->name); | ||
2389 | |||
2390 | err = hermes_write_ltv(hw, USER_BAP, | ||
2391 | HERMES_RID_CNFGROUPADDRESSES, | ||
2392 | HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN), | ||
2393 | &mclist); | ||
2394 | if (err) | ||
2395 | printk(KERN_ERR "%s: Error %d setting multicast list.\n", | ||
2396 | priv->ndev->name, err); | ||
2397 | else | ||
2398 | priv->mc_count = mc_count; | ||
2399 | } | ||
2400 | return err; | ||
2401 | } | ||
2402 | |||
2403 | /* FIXME: return int? */ | 1948 | /* FIXME: return int? */ |
2404 | static void | 1949 | static void |
2405 | __orinoco_set_multicast_list(struct net_device *dev) | 1950 | __orinoco_set_multicast_list(struct net_device *dev) |
@@ -3170,132 +2715,6 @@ EXPORT_SYMBOL(free_orinocodev); | |||
3170 | /* Wireless extensions */ | 2715 | /* Wireless extensions */ |
3171 | /********************************************************************/ | 2716 | /********************************************************************/ |
3172 | 2717 | ||
3173 | /* Return : < 0 -> error code ; >= 0 -> length */ | ||
3174 | static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, | ||
3175 | char buf[IW_ESSID_MAX_SIZE+1]) | ||
3176 | { | ||
3177 | hermes_t *hw = &priv->hw; | ||
3178 | int err = 0; | ||
3179 | struct hermes_idstring essidbuf; | ||
3180 | char *p = (char *)(&essidbuf.val); | ||
3181 | int len; | ||
3182 | unsigned long flags; | ||
3183 | |||
3184 | if (orinoco_lock(priv, &flags) != 0) | ||
3185 | return -EBUSY; | ||
3186 | |||
3187 | if (strlen(priv->desired_essid) > 0) { | ||
3188 | /* We read the desired SSID from the hardware rather | ||
3189 | than from priv->desired_essid, just in case the | ||
3190 | firmware is allowed to change it on us. I'm not | ||
3191 | sure about this */ | ||
3192 | /* My guess is that the OWNSSID should always be whatever | ||
3193 | * we set to the card, whereas CURRENT_SSID is the one that | ||
3194 | * may change... - Jean II */ | ||
3195 | u16 rid; | ||
3196 | |||
3197 | *active = 1; | ||
3198 | |||
3199 | rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : | ||
3200 | HERMES_RID_CNFDESIREDSSID; | ||
3201 | |||
3202 | err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), | ||
3203 | NULL, &essidbuf); | ||
3204 | if (err) | ||
3205 | goto fail_unlock; | ||
3206 | } else { | ||
3207 | *active = 0; | ||
3208 | |||
3209 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, | ||
3210 | sizeof(essidbuf), NULL, &essidbuf); | ||
3211 | if (err) | ||
3212 | goto fail_unlock; | ||
3213 | } | ||
3214 | |||
3215 | len = le16_to_cpu(essidbuf.len); | ||
3216 | BUG_ON(len > IW_ESSID_MAX_SIZE); | ||
3217 | |||
3218 | memset(buf, 0, IW_ESSID_MAX_SIZE); | ||
3219 | memcpy(buf, p, len); | ||
3220 | err = len; | ||
3221 | |||
3222 | fail_unlock: | ||
3223 | orinoco_unlock(priv, &flags); | ||
3224 | |||
3225 | return err; | ||
3226 | } | ||
3227 | |||
3228 | static int orinoco_hw_get_freq(struct orinoco_private *priv) | ||
3229 | { | ||
3230 | |||
3231 | hermes_t *hw = &priv->hw; | ||
3232 | int err = 0; | ||
3233 | u16 channel; | ||
3234 | int freq = 0; | ||
3235 | unsigned long flags; | ||
3236 | |||
3237 | if (orinoco_lock(priv, &flags) != 0) | ||
3238 | return -EBUSY; | ||
3239 | |||
3240 | err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, | ||
3241 | &channel); | ||
3242 | if (err) | ||
3243 | goto out; | ||
3244 | |||
3245 | /* Intersil firmware 1.3.5 returns 0 when the interface is down */ | ||
3246 | if (channel == 0) { | ||
3247 | err = -EBUSY; | ||
3248 | goto out; | ||
3249 | } | ||
3250 | |||
3251 | if ((channel < 1) || (channel > NUM_CHANNELS)) { | ||
3252 | printk(KERN_WARNING "%s: Channel out of range (%d)!\n", | ||
3253 | priv->ndev->name, channel); | ||
3254 | err = -EBUSY; | ||
3255 | goto out; | ||
3256 | |||
3257 | } | ||
3258 | freq = ieee80211_dsss_chan_to_freq(channel); | ||
3259 | |||
3260 | out: | ||
3261 | orinoco_unlock(priv, &flags); | ||
3262 | |||
3263 | if (err > 0) | ||
3264 | err = -EBUSY; | ||
3265 | return err ? err : freq; | ||
3266 | } | ||
3267 | |||
3268 | static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, | ||
3269 | int *numrates, s32 *rates, int max) | ||
3270 | { | ||
3271 | hermes_t *hw = &priv->hw; | ||
3272 | struct hermes_idstring list; | ||
3273 | unsigned char *p = (unsigned char *)&list.val; | ||
3274 | int err = 0; | ||
3275 | int num; | ||
3276 | int i; | ||
3277 | unsigned long flags; | ||
3278 | |||
3279 | if (orinoco_lock(priv, &flags) != 0) | ||
3280 | return -EBUSY; | ||
3281 | |||
3282 | err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, | ||
3283 | sizeof(list), NULL, &list); | ||
3284 | orinoco_unlock(priv, &flags); | ||
3285 | |||
3286 | if (err) | ||
3287 | return err; | ||
3288 | |||
3289 | num = le16_to_cpu(list.len); | ||
3290 | *numrates = num; | ||
3291 | num = min(num, max); | ||
3292 | |||
3293 | for (i = 0; i < num; i++) | ||
3294 | rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */ | ||
3295 | |||
3296 | return 0; | ||
3297 | } | ||
3298 | |||
3299 | static int orinoco_ioctl_getname(struct net_device *dev, | 2718 | static int orinoco_ioctl_getname(struct net_device *dev, |
3300 | struct iw_request_info *info, | 2719 | struct iw_request_info *info, |
3301 | char *name, | 2720 | char *name, |