hw.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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. k = 100;
  323. do {
  324. k--;
  325. udelay(1000);
  326. ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
  327. &xmitting);
  328. if (ret)
  329. break;
  330. } while ((k > 0) && xmitting);
  331. if (k == 0)
  332. ret = -ETIMEDOUT;
  333. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  334. HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
  335. &buf);
  336. return ret ? ret : err;
  337. }
  338. int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
  339. {
  340. hermes_t *hw = &priv->hw;
  341. int err;
  342. memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
  343. err = hermes_write_wordrec(hw, USER_BAP,
  344. HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
  345. key_idx);
  346. if (err)
  347. printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
  348. priv->ndev->name, err, key_idx);
  349. return err;
  350. }
  351. int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
  352. struct dev_addr_list *mc_list,
  353. int mc_count, int promisc)
  354. {
  355. hermes_t *hw = &priv->hw;
  356. int err = 0;
  357. if (promisc != priv->promiscuous) {
  358. err = hermes_write_wordrec(hw, USER_BAP,
  359. HERMES_RID_CNFPROMISCUOUSMODE,
  360. promisc);
  361. if (err) {
  362. printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
  363. priv->ndev->name, err);
  364. } else
  365. priv->promiscuous = promisc;
  366. }
  367. /* If we're not in promiscuous mode, then we need to set the
  368. * group address if either we want to multicast, or if we were
  369. * multicasting and want to stop */
  370. if (!promisc && (mc_count || priv->mc_count)) {
  371. struct dev_mc_list *p = mc_list;
  372. struct hermes_multicast mclist;
  373. int i;
  374. for (i = 0; i < mc_count; i++) {
  375. /* paranoia: is list shorter than mc_count? */
  376. BUG_ON(!p);
  377. /* paranoia: bad address size in list? */
  378. BUG_ON(p->dmi_addrlen != ETH_ALEN);
  379. memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
  380. p = p->next;
  381. }
  382. if (p)
  383. printk(KERN_WARNING "%s: Multicast list is "
  384. "longer than mc_count\n", priv->ndev->name);
  385. err = hermes_write_ltv(hw, USER_BAP,
  386. HERMES_RID_CNFGROUPADDRESSES,
  387. HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
  388. &mclist);
  389. if (err)
  390. printk(KERN_ERR "%s: Error %d setting multicast list.\n",
  391. priv->ndev->name, err);
  392. else
  393. priv->mc_count = mc_count;
  394. }
  395. return err;
  396. }
  397. /* Return : < 0 -> error code ; >= 0 -> length */
  398. int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
  399. char buf[IW_ESSID_MAX_SIZE+1])
  400. {
  401. hermes_t *hw = &priv->hw;
  402. int err = 0;
  403. struct hermes_idstring essidbuf;
  404. char *p = (char *)(&essidbuf.val);
  405. int len;
  406. unsigned long flags;
  407. if (orinoco_lock(priv, &flags) != 0)
  408. return -EBUSY;
  409. if (strlen(priv->desired_essid) > 0) {
  410. /* We read the desired SSID from the hardware rather
  411. than from priv->desired_essid, just in case the
  412. firmware is allowed to change it on us. I'm not
  413. sure about this */
  414. /* My guess is that the OWNSSID should always be whatever
  415. * we set to the card, whereas CURRENT_SSID is the one that
  416. * may change... - Jean II */
  417. u16 rid;
  418. *active = 1;
  419. rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
  420. HERMES_RID_CNFDESIREDSSID;
  421. err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
  422. NULL, &essidbuf);
  423. if (err)
  424. goto fail_unlock;
  425. } else {
  426. *active = 0;
  427. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
  428. sizeof(essidbuf), NULL, &essidbuf);
  429. if (err)
  430. goto fail_unlock;
  431. }
  432. len = le16_to_cpu(essidbuf.len);
  433. BUG_ON(len > IW_ESSID_MAX_SIZE);
  434. memset(buf, 0, IW_ESSID_MAX_SIZE);
  435. memcpy(buf, p, len);
  436. err = len;
  437. fail_unlock:
  438. orinoco_unlock(priv, &flags);
  439. return err;
  440. }
  441. int orinoco_hw_get_freq(struct orinoco_private *priv)
  442. {
  443. hermes_t *hw = &priv->hw;
  444. int err = 0;
  445. u16 channel;
  446. int freq = 0;
  447. unsigned long flags;
  448. if (orinoco_lock(priv, &flags) != 0)
  449. return -EBUSY;
  450. err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
  451. &channel);
  452. if (err)
  453. goto out;
  454. /* Intersil firmware 1.3.5 returns 0 when the interface is down */
  455. if (channel == 0) {
  456. err = -EBUSY;
  457. goto out;
  458. }
  459. if ((channel < 1) || (channel > NUM_CHANNELS)) {
  460. printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
  461. priv->ndev->name, channel);
  462. err = -EBUSY;
  463. goto out;
  464. }
  465. freq = ieee80211_dsss_chan_to_freq(channel);
  466. out:
  467. orinoco_unlock(priv, &flags);
  468. if (err > 0)
  469. err = -EBUSY;
  470. return err ? err : freq;
  471. }
  472. int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
  473. int *numrates, s32 *rates, int max)
  474. {
  475. hermes_t *hw = &priv->hw;
  476. struct hermes_idstring list;
  477. unsigned char *p = (unsigned char *)&list.val;
  478. int err = 0;
  479. int num;
  480. int i;
  481. unsigned long flags;
  482. if (orinoco_lock(priv, &flags) != 0)
  483. return -EBUSY;
  484. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
  485. sizeof(list), NULL, &list);
  486. orinoco_unlock(priv, &flags);
  487. if (err)
  488. return err;
  489. num = le16_to_cpu(list.len);
  490. *numrates = num;
  491. num = min(num, max);
  492. for (i = 0; i < num; i++)
  493. rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
  494. return 0;
  495. }