hw.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /* Encapsulate basic setting changes and retrieval on Hermes hardware
  2. *
  3. * See copyright notice in main.c
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/if_arp.h>
  7. #include <linux/ieee80211.h>
  8. #include <linux/wireless.h>
  9. #include "hermes.h"
  10. #include "hermes_rid.h"
  11. #include "orinoco.h"
  12. #include "hw.h"
  13. /********************************************************************/
  14. /* Data tables */
  15. /********************************************************************/
  16. /* This tables gives the actual meanings of the bitrate IDs returned
  17. * by the firmware. */
  18. static const struct {
  19. int bitrate; /* in 100s of kilobits */
  20. int automatic;
  21. u16 agere_txratectrl;
  22. u16 intersil_txratectrl;
  23. } bitrate_table[] = {
  24. {110, 1, 3, 15}, /* Entry 0 is the default */
  25. {10, 0, 1, 1},
  26. {10, 1, 1, 1},
  27. {20, 0, 2, 2},
  28. {20, 1, 6, 3},
  29. {55, 0, 4, 4},
  30. {55, 1, 7, 7},
  31. {110, 0, 5, 8},
  32. };
  33. #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
  34. int orinoco_get_bitratemode(int bitrate, int automatic)
  35. {
  36. int ratemode = -1;
  37. int i;
  38. if ((bitrate != 10) && (bitrate != 20) &&
  39. (bitrate != 55) && (bitrate != 110))
  40. return ratemode;
  41. for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
  42. if ((bitrate_table[i].bitrate == bitrate) &&
  43. (bitrate_table[i].automatic == automatic)) {
  44. ratemode = i;
  45. break;
  46. }
  47. }
  48. return ratemode;
  49. }
  50. void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
  51. {
  52. BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
  53. *bitrate = bitrate_table[ratemode].bitrate * 100000;
  54. *automatic = bitrate_table[ratemode].automatic;
  55. }
  56. /* Get tsc from the firmware */
  57. int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
  58. {
  59. hermes_t *hw = &priv->hw;
  60. int err = 0;
  61. u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
  62. if ((key < 0) || (key > 4))
  63. return -EINVAL;
  64. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
  65. sizeof(tsc_arr), NULL, &tsc_arr);
  66. if (!err)
  67. memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
  68. return err;
  69. }
  70. int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
  71. {
  72. hermes_t *hw = &priv->hw;
  73. int ratemode = priv->bitratemode;
  74. int err = 0;
  75. if (ratemode >= BITRATE_TABLE_SIZE) {
  76. printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
  77. priv->ndev->name, ratemode);
  78. return -EINVAL;
  79. }
  80. switch (priv->firmware_type) {
  81. case FIRMWARE_TYPE_AGERE:
  82. err = hermes_write_wordrec(hw, USER_BAP,
  83. HERMES_RID_CNFTXRATECONTROL,
  84. bitrate_table[ratemode].agere_txratectrl);
  85. break;
  86. case FIRMWARE_TYPE_INTERSIL:
  87. case FIRMWARE_TYPE_SYMBOL:
  88. err = hermes_write_wordrec(hw, USER_BAP,
  89. HERMES_RID_CNFTXRATECONTROL,
  90. bitrate_table[ratemode].intersil_txratectrl);
  91. break;
  92. default:
  93. BUG();
  94. }
  95. return err;
  96. }
  97. int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
  98. {
  99. hermes_t *hw = &priv->hw;
  100. int i;
  101. int err = 0;
  102. u16 val;
  103. err = hermes_read_wordrec(hw, USER_BAP,
  104. HERMES_RID_CURRENTTXRATE, &val);
  105. if (err)
  106. return err;
  107. switch (priv->firmware_type) {
  108. case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
  109. /* Note : in Lucent firmware, the return value of
  110. * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
  111. * and therefore is totally different from the
  112. * encoding of HERMES_RID_CNFTXRATECONTROL.
  113. * Don't forget that 6Mb/s is really 5.5Mb/s */
  114. if (val == 6)
  115. *bitrate = 5500000;
  116. else
  117. *bitrate = val * 1000000;
  118. break;
  119. case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
  120. case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
  121. for (i = 0; i < BITRATE_TABLE_SIZE; i++)
  122. if (bitrate_table[i].intersil_txratectrl == val)
  123. break;
  124. if (i >= BITRATE_TABLE_SIZE)
  125. printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
  126. priv->ndev->name, val);
  127. *bitrate = bitrate_table[i].bitrate * 100000;
  128. break;
  129. default:
  130. BUG();
  131. }
  132. return err;
  133. }
  134. /* Set fixed AP address */
  135. int __orinoco_hw_set_wap(struct orinoco_private *priv)
  136. {
  137. int roaming_flag;
  138. int err = 0;
  139. hermes_t *hw = &priv->hw;
  140. switch (priv->firmware_type) {
  141. case FIRMWARE_TYPE_AGERE:
  142. /* not supported */
  143. break;
  144. case FIRMWARE_TYPE_INTERSIL:
  145. if (priv->bssid_fixed)
  146. roaming_flag = 2;
  147. else
  148. roaming_flag = 1;
  149. err = hermes_write_wordrec(hw, USER_BAP,
  150. HERMES_RID_CNFROAMINGMODE,
  151. roaming_flag);
  152. break;
  153. case FIRMWARE_TYPE_SYMBOL:
  154. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  155. HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
  156. &priv->desired_bssid);
  157. break;
  158. }
  159. return err;
  160. }
  161. /* Change the WEP keys and/or the current keys. Can be called
  162. * either from __orinoco_hw_setup_enc() or directly from
  163. * orinoco_ioctl_setiwencode(). In the later case the association
  164. * with the AP is not broken (if the firmware can handle it),
  165. * which is needed for 802.1x implementations. */
  166. int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
  167. {
  168. hermes_t *hw = &priv->hw;
  169. int err = 0;
  170. switch (priv->firmware_type) {
  171. case FIRMWARE_TYPE_AGERE:
  172. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  173. HERMES_RID_CNFWEPKEYS_AGERE,
  174. &priv->keys);
  175. if (err)
  176. return err;
  177. err = hermes_write_wordrec(hw, USER_BAP,
  178. HERMES_RID_CNFTXKEY_AGERE,
  179. priv->tx_key);
  180. if (err)
  181. return err;
  182. break;
  183. case FIRMWARE_TYPE_INTERSIL:
  184. case FIRMWARE_TYPE_SYMBOL:
  185. {
  186. int keylen;
  187. int i;
  188. /* Force uniform key length to work around
  189. * firmware bugs */
  190. keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
  191. if (keylen > LARGE_KEY_SIZE) {
  192. printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
  193. priv->ndev->name, priv->tx_key, keylen);
  194. return -E2BIG;
  195. }
  196. /* Write all 4 keys */
  197. for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
  198. err = hermes_write_ltv(hw, USER_BAP,
  199. HERMES_RID_CNFDEFAULTKEY0 + i,
  200. HERMES_BYTES_TO_RECLEN(keylen),
  201. priv->keys[i].data);
  202. if (err)
  203. return err;
  204. }
  205. /* Write the index of the key used in transmission */
  206. err = hermes_write_wordrec(hw, USER_BAP,
  207. HERMES_RID_CNFWEPDEFAULTKEYID,
  208. priv->tx_key);
  209. if (err)
  210. return err;
  211. }
  212. break;
  213. }
  214. return 0;
  215. }
  216. int __orinoco_hw_setup_enc(struct orinoco_private *priv)
  217. {
  218. hermes_t *hw = &priv->hw;
  219. int err = 0;
  220. int master_wep_flag;
  221. int auth_flag;
  222. int enc_flag;
  223. /* Setup WEP keys for WEP and WPA */
  224. if (priv->encode_alg)
  225. __orinoco_hw_setup_wepkeys(priv);
  226. if (priv->wep_restrict)
  227. auth_flag = HERMES_AUTH_SHARED_KEY;
  228. else
  229. auth_flag = HERMES_AUTH_OPEN;
  230. if (priv->wpa_enabled)
  231. enc_flag = 2;
  232. else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
  233. enc_flag = 1;
  234. else
  235. enc_flag = 0;
  236. switch (priv->firmware_type) {
  237. case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
  238. if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
  239. /* Enable the shared-key authentication. */
  240. err = hermes_write_wordrec(hw, USER_BAP,
  241. HERMES_RID_CNFAUTHENTICATION_AGERE,
  242. auth_flag);
  243. }
  244. err = hermes_write_wordrec(hw, USER_BAP,
  245. HERMES_RID_CNFWEPENABLED_AGERE,
  246. enc_flag);
  247. if (err)
  248. return err;
  249. if (priv->has_wpa) {
  250. /* Set WPA key management */
  251. err = hermes_write_wordrec(hw, USER_BAP,
  252. HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
  253. priv->key_mgmt);
  254. if (err)
  255. return err;
  256. }
  257. break;
  258. case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
  259. case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
  260. if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
  261. if (priv->wep_restrict ||
  262. (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
  263. master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
  264. HERMES_WEP_EXCL_UNENCRYPTED;
  265. else
  266. master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
  267. err = hermes_write_wordrec(hw, USER_BAP,
  268. HERMES_RID_CNFAUTHENTICATION,
  269. auth_flag);
  270. if (err)
  271. return err;
  272. } else
  273. master_wep_flag = 0;
  274. if (priv->iw_mode == IW_MODE_MONITOR)
  275. master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
  276. /* Master WEP setting : on/off */
  277. err = hermes_write_wordrec(hw, USER_BAP,
  278. HERMES_RID_CNFWEPFLAGS_INTERSIL,
  279. master_wep_flag);
  280. if (err)
  281. return err;
  282. break;
  283. }
  284. return 0;
  285. }
  286. /* key must be 32 bytes, including the tx and rx MIC keys.
  287. * rsc must be 8 bytes
  288. * tsc must be 8 bytes or NULL
  289. */
  290. int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
  291. u8 *key, u8 *rsc, u8 *tsc)
  292. {
  293. struct {
  294. __le16 idx;
  295. u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
  296. u8 key[TKIP_KEYLEN];
  297. u8 tx_mic[MIC_KEYLEN];
  298. u8 rx_mic[MIC_KEYLEN];
  299. u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
  300. } __attribute__ ((packed)) buf;
  301. int ret;
  302. int err;
  303. int k;
  304. u16 xmitting;
  305. key_idx &= 0x3;
  306. if (set_tx)
  307. key_idx |= 0x8000;
  308. buf.idx = cpu_to_le16(key_idx);
  309. memcpy(buf.key, key,
  310. sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
  311. if (rsc == NULL)
  312. memset(buf.rsc, 0, sizeof(buf.rsc));
  313. else
  314. memcpy(buf.rsc, rsc, sizeof(buf.rsc));
  315. if (tsc == NULL) {
  316. memset(buf.tsc, 0, sizeof(buf.tsc));
  317. buf.tsc[4] = 0x10;
  318. } else {
  319. memcpy(buf.tsc, tsc, sizeof(buf.tsc));
  320. }
  321. /* Wait upto 100ms for tx queue to empty */
  322. for (k = 100; k > 0; k--) {
  323. udelay(1000);
  324. ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
  325. &xmitting);
  326. if (ret || !xmitting)
  327. break;
  328. }
  329. if (k == 0)
  330. ret = -ETIMEDOUT;
  331. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  332. HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
  333. &buf);
  334. return ret ? ret : err;
  335. }
  336. int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
  337. {
  338. hermes_t *hw = &priv->hw;
  339. int err;
  340. memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
  341. err = hermes_write_wordrec(hw, USER_BAP,
  342. HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
  343. key_idx);
  344. if (err)
  345. printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
  346. priv->ndev->name, err, key_idx);
  347. return err;
  348. }
  349. int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
  350. struct dev_addr_list *mc_list,
  351. int mc_count, int promisc)
  352. {
  353. hermes_t *hw = &priv->hw;
  354. int err = 0;
  355. if (promisc != priv->promiscuous) {
  356. err = hermes_write_wordrec(hw, USER_BAP,
  357. HERMES_RID_CNFPROMISCUOUSMODE,
  358. promisc);
  359. if (err) {
  360. printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
  361. priv->ndev->name, err);
  362. } else
  363. priv->promiscuous = promisc;
  364. }
  365. /* If we're not in promiscuous mode, then we need to set the
  366. * group address if either we want to multicast, or if we were
  367. * multicasting and want to stop */
  368. if (!promisc && (mc_count || priv->mc_count)) {
  369. struct dev_mc_list *p = mc_list;
  370. struct hermes_multicast mclist;
  371. int i;
  372. for (i = 0; i < mc_count; i++) {
  373. /* paranoia: is list shorter than mc_count? */
  374. BUG_ON(!p);
  375. /* paranoia: bad address size in list? */
  376. BUG_ON(p->dmi_addrlen != ETH_ALEN);
  377. memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
  378. p = p->next;
  379. }
  380. if (p)
  381. printk(KERN_WARNING "%s: Multicast list is "
  382. "longer than mc_count\n", priv->ndev->name);
  383. err = hermes_write_ltv(hw, USER_BAP,
  384. HERMES_RID_CNFGROUPADDRESSES,
  385. HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
  386. &mclist);
  387. if (err)
  388. printk(KERN_ERR "%s: Error %d setting multicast list.\n",
  389. priv->ndev->name, err);
  390. else
  391. priv->mc_count = mc_count;
  392. }
  393. return err;
  394. }
  395. /* Return : < 0 -> error code ; >= 0 -> length */
  396. int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
  397. char buf[IW_ESSID_MAX_SIZE+1])
  398. {
  399. hermes_t *hw = &priv->hw;
  400. int err = 0;
  401. struct hermes_idstring essidbuf;
  402. char *p = (char *)(&essidbuf.val);
  403. int len;
  404. unsigned long flags;
  405. if (orinoco_lock(priv, &flags) != 0)
  406. return -EBUSY;
  407. if (strlen(priv->desired_essid) > 0) {
  408. /* We read the desired SSID from the hardware rather
  409. than from priv->desired_essid, just in case the
  410. firmware is allowed to change it on us. I'm not
  411. sure about this */
  412. /* My guess is that the OWNSSID should always be whatever
  413. * we set to the card, whereas CURRENT_SSID is the one that
  414. * may change... - Jean II */
  415. u16 rid;
  416. *active = 1;
  417. rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
  418. HERMES_RID_CNFDESIREDSSID;
  419. err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
  420. NULL, &essidbuf);
  421. if (err)
  422. goto fail_unlock;
  423. } else {
  424. *active = 0;
  425. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
  426. sizeof(essidbuf), NULL, &essidbuf);
  427. if (err)
  428. goto fail_unlock;
  429. }
  430. len = le16_to_cpu(essidbuf.len);
  431. BUG_ON(len > IW_ESSID_MAX_SIZE);
  432. memset(buf, 0, IW_ESSID_MAX_SIZE);
  433. memcpy(buf, p, len);
  434. err = len;
  435. fail_unlock:
  436. orinoco_unlock(priv, &flags);
  437. return err;
  438. }
  439. int orinoco_hw_get_freq(struct orinoco_private *priv)
  440. {
  441. hermes_t *hw = &priv->hw;
  442. int err = 0;
  443. u16 channel;
  444. int freq = 0;
  445. unsigned long flags;
  446. if (orinoco_lock(priv, &flags) != 0)
  447. return -EBUSY;
  448. err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
  449. &channel);
  450. if (err)
  451. goto out;
  452. /* Intersil firmware 1.3.5 returns 0 when the interface is down */
  453. if (channel == 0) {
  454. err = -EBUSY;
  455. goto out;
  456. }
  457. if ((channel < 1) || (channel > NUM_CHANNELS)) {
  458. printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
  459. priv->ndev->name, channel);
  460. err = -EBUSY;
  461. goto out;
  462. }
  463. freq = ieee80211_dsss_chan_to_freq(channel);
  464. out:
  465. orinoco_unlock(priv, &flags);
  466. if (err > 0)
  467. err = -EBUSY;
  468. return err ? err : freq;
  469. }
  470. int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
  471. int *numrates, s32 *rates, int max)
  472. {
  473. hermes_t *hw = &priv->hw;
  474. struct hermes_idstring list;
  475. unsigned char *p = (unsigned char *)&list.val;
  476. int err = 0;
  477. int num;
  478. int i;
  479. unsigned long flags;
  480. if (orinoco_lock(priv, &flags) != 0)
  481. return -EBUSY;
  482. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
  483. sizeof(list), NULL, &list);
  484. orinoco_unlock(priv, &flags);
  485. if (err)
  486. return err;
  487. num = le16_to_cpu(list.len);
  488. *numrates = num;
  489. num = min(num, max);
  490. for (i = 0; i < num; i++)
  491. rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
  492. return 0;
  493. }