hw.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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. #define SYMBOL_MAX_VER_LEN (14)
  14. /********************************************************************/
  15. /* Data tables */
  16. /********************************************************************/
  17. /* This tables gives the actual meanings of the bitrate IDs returned
  18. * by the firmware. */
  19. static const struct {
  20. int bitrate; /* in 100s of kilobits */
  21. int automatic;
  22. u16 agere_txratectrl;
  23. u16 intersil_txratectrl;
  24. } bitrate_table[] = {
  25. {110, 1, 3, 15}, /* Entry 0 is the default */
  26. {10, 0, 1, 1},
  27. {10, 1, 1, 1},
  28. {20, 0, 2, 2},
  29. {20, 1, 6, 3},
  30. {55, 0, 4, 4},
  31. {55, 1, 7, 7},
  32. {110, 0, 5, 8},
  33. };
  34. #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
  35. /* Firmware version encoding */
  36. struct comp_id {
  37. u16 id, variant, major, minor;
  38. } __attribute__ ((packed));
  39. static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
  40. {
  41. if (nic_id->id < 0x8000)
  42. return FIRMWARE_TYPE_AGERE;
  43. else if (nic_id->id == 0x8000 && nic_id->major == 0)
  44. return FIRMWARE_TYPE_SYMBOL;
  45. else
  46. return FIRMWARE_TYPE_INTERSIL;
  47. }
  48. /* Set priv->firmware type, determine firmware properties */
  49. int determine_fw_capabilities(struct orinoco_private *priv)
  50. {
  51. struct net_device *dev = priv->ndev;
  52. hermes_t *hw = &priv->hw;
  53. int err;
  54. struct comp_id nic_id, sta_id;
  55. unsigned int firmver;
  56. char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
  57. /* Get the hardware version */
  58. err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
  59. if (err) {
  60. printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
  61. dev->name, err);
  62. return err;
  63. }
  64. le16_to_cpus(&nic_id.id);
  65. le16_to_cpus(&nic_id.variant);
  66. le16_to_cpus(&nic_id.major);
  67. le16_to_cpus(&nic_id.minor);
  68. printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
  69. dev->name, nic_id.id, nic_id.variant,
  70. nic_id.major, nic_id.minor);
  71. priv->firmware_type = determine_firmware_type(&nic_id);
  72. /* Get the firmware version */
  73. err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
  74. if (err) {
  75. printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
  76. dev->name, err);
  77. return err;
  78. }
  79. le16_to_cpus(&sta_id.id);
  80. le16_to_cpus(&sta_id.variant);
  81. le16_to_cpus(&sta_id.major);
  82. le16_to_cpus(&sta_id.minor);
  83. printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
  84. dev->name, sta_id.id, sta_id.variant,
  85. sta_id.major, sta_id.minor);
  86. switch (sta_id.id) {
  87. case 0x15:
  88. printk(KERN_ERR "%s: Primary firmware is active\n",
  89. dev->name);
  90. return -ENODEV;
  91. case 0x14b:
  92. printk(KERN_ERR "%s: Tertiary firmware is active\n",
  93. dev->name);
  94. return -ENODEV;
  95. case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
  96. case 0x21: /* Symbol Spectrum24 Trilogy */
  97. break;
  98. default:
  99. printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
  100. dev->name);
  101. break;
  102. }
  103. /* Default capabilities */
  104. priv->has_sensitivity = 1;
  105. priv->has_mwo = 0;
  106. priv->has_preamble = 0;
  107. priv->has_port3 = 1;
  108. priv->has_ibss = 1;
  109. priv->has_wep = 0;
  110. priv->has_big_wep = 0;
  111. priv->has_alt_txcntl = 0;
  112. priv->has_ext_scan = 0;
  113. priv->has_wpa = 0;
  114. priv->do_fw_download = 0;
  115. /* Determine capabilities from the firmware version */
  116. switch (priv->firmware_type) {
  117. case FIRMWARE_TYPE_AGERE:
  118. /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
  119. ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
  120. snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
  121. "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
  122. firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
  123. priv->has_ibss = (firmver >= 0x60006);
  124. priv->has_wep = (firmver >= 0x40020);
  125. priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
  126. Gold cards from the others? */
  127. priv->has_mwo = (firmver >= 0x60000);
  128. priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
  129. priv->ibss_port = 1;
  130. priv->has_hostscan = (firmver >= 0x8000a);
  131. priv->do_fw_download = 1;
  132. priv->broken_monitor = (firmver >= 0x80000);
  133. priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
  134. priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
  135. priv->has_wpa = (firmver >= 0x9002a);
  136. /* Tested with Agere firmware :
  137. * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
  138. * Tested CableTron firmware : 4.32 => Anton */
  139. break;
  140. case FIRMWARE_TYPE_SYMBOL:
  141. /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
  142. /* Intel MAC : 00:02:B3:* */
  143. /* 3Com MAC : 00:50:DA:* */
  144. memset(tmp, 0, sizeof(tmp));
  145. /* Get the Symbol firmware version */
  146. err = hermes_read_ltv(hw, USER_BAP,
  147. HERMES_RID_SECONDARYVERSION_SYMBOL,
  148. SYMBOL_MAX_VER_LEN, NULL, &tmp);
  149. if (err) {
  150. printk(KERN_WARNING
  151. "%s: Error %d reading Symbol firmware info. "
  152. "Wildly guessing capabilities...\n",
  153. dev->name, err);
  154. firmver = 0;
  155. tmp[0] = '\0';
  156. } else {
  157. /* The firmware revision is a string, the format is
  158. * something like : "V2.20-01".
  159. * Quick and dirty parsing... - Jean II
  160. */
  161. firmver = ((tmp[1] - '0') << 16)
  162. | ((tmp[3] - '0') << 12)
  163. | ((tmp[4] - '0') << 8)
  164. | ((tmp[6] - '0') << 4)
  165. | (tmp[7] - '0');
  166. tmp[SYMBOL_MAX_VER_LEN] = '\0';
  167. }
  168. snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
  169. "Symbol %s", tmp);
  170. priv->has_ibss = (firmver >= 0x20000);
  171. priv->has_wep = (firmver >= 0x15012);
  172. priv->has_big_wep = (firmver >= 0x20000);
  173. priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
  174. (firmver >= 0x29000 && firmver < 0x30000) ||
  175. firmver >= 0x31000;
  176. priv->has_preamble = (firmver >= 0x20000);
  177. priv->ibss_port = 4;
  178. /* Symbol firmware is found on various cards, but
  179. * there has been no attempt to check firmware
  180. * download on non-spectrum_cs based cards.
  181. *
  182. * Given that the Agere firmware download works
  183. * differently, we should avoid doing a firmware
  184. * download with the Symbol algorithm on non-spectrum
  185. * cards.
  186. *
  187. * For now we can identify a spectrum_cs based card
  188. * because it has a firmware reset function.
  189. */
  190. priv->do_fw_download = (priv->stop_fw != NULL);
  191. priv->broken_disableport = (firmver == 0x25013) ||
  192. (firmver >= 0x30000 && firmver <= 0x31000);
  193. priv->has_hostscan = (firmver >= 0x31001) ||
  194. (firmver >= 0x29057 && firmver < 0x30000);
  195. /* Tested with Intel firmware : 0x20015 => Jean II */
  196. /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
  197. break;
  198. case FIRMWARE_TYPE_INTERSIL:
  199. /* D-Link, Linksys, Adtron, ZoomAir, and many others...
  200. * Samsung, Compaq 100/200 and Proxim are slightly
  201. * different and less well tested */
  202. /* D-Link MAC : 00:40:05:* */
  203. /* Addtron MAC : 00:90:D1:* */
  204. snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
  205. "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
  206. sta_id.variant);
  207. firmver = ((unsigned long)sta_id.major << 16) |
  208. ((unsigned long)sta_id.minor << 8) | sta_id.variant;
  209. priv->has_ibss = (firmver >= 0x000700); /* FIXME */
  210. priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
  211. priv->has_pm = (firmver >= 0x000700);
  212. priv->has_hostscan = (firmver >= 0x010301);
  213. if (firmver >= 0x000800)
  214. priv->ibss_port = 0;
  215. else {
  216. printk(KERN_NOTICE "%s: Intersil firmware earlier "
  217. "than v0.8.x - several features not supported\n",
  218. dev->name);
  219. priv->ibss_port = 1;
  220. }
  221. break;
  222. }
  223. printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
  224. priv->fw_name);
  225. return 0;
  226. }
  227. int orinoco_get_bitratemode(int bitrate, int automatic)
  228. {
  229. int ratemode = -1;
  230. int i;
  231. if ((bitrate != 10) && (bitrate != 20) &&
  232. (bitrate != 55) && (bitrate != 110))
  233. return ratemode;
  234. for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
  235. if ((bitrate_table[i].bitrate == bitrate) &&
  236. (bitrate_table[i].automatic == automatic)) {
  237. ratemode = i;
  238. break;
  239. }
  240. }
  241. return ratemode;
  242. }
  243. void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
  244. {
  245. BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
  246. *bitrate = bitrate_table[ratemode].bitrate * 100000;
  247. *automatic = bitrate_table[ratemode].automatic;
  248. }
  249. /* Get tsc from the firmware */
  250. int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
  251. {
  252. hermes_t *hw = &priv->hw;
  253. int err = 0;
  254. u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
  255. if ((key < 0) || (key > 4))
  256. return -EINVAL;
  257. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
  258. sizeof(tsc_arr), NULL, &tsc_arr);
  259. if (!err)
  260. memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
  261. return err;
  262. }
  263. int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
  264. {
  265. hermes_t *hw = &priv->hw;
  266. int ratemode = priv->bitratemode;
  267. int err = 0;
  268. if (ratemode >= BITRATE_TABLE_SIZE) {
  269. printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
  270. priv->ndev->name, ratemode);
  271. return -EINVAL;
  272. }
  273. switch (priv->firmware_type) {
  274. case FIRMWARE_TYPE_AGERE:
  275. err = hermes_write_wordrec(hw, USER_BAP,
  276. HERMES_RID_CNFTXRATECONTROL,
  277. bitrate_table[ratemode].agere_txratectrl);
  278. break;
  279. case FIRMWARE_TYPE_INTERSIL:
  280. case FIRMWARE_TYPE_SYMBOL:
  281. err = hermes_write_wordrec(hw, USER_BAP,
  282. HERMES_RID_CNFTXRATECONTROL,
  283. bitrate_table[ratemode].intersil_txratectrl);
  284. break;
  285. default:
  286. BUG();
  287. }
  288. return err;
  289. }
  290. int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
  291. {
  292. hermes_t *hw = &priv->hw;
  293. int i;
  294. int err = 0;
  295. u16 val;
  296. err = hermes_read_wordrec(hw, USER_BAP,
  297. HERMES_RID_CURRENTTXRATE, &val);
  298. if (err)
  299. return err;
  300. switch (priv->firmware_type) {
  301. case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
  302. /* Note : in Lucent firmware, the return value of
  303. * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
  304. * and therefore is totally different from the
  305. * encoding of HERMES_RID_CNFTXRATECONTROL.
  306. * Don't forget that 6Mb/s is really 5.5Mb/s */
  307. if (val == 6)
  308. *bitrate = 5500000;
  309. else
  310. *bitrate = val * 1000000;
  311. break;
  312. case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
  313. case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
  314. for (i = 0; i < BITRATE_TABLE_SIZE; i++)
  315. if (bitrate_table[i].intersil_txratectrl == val)
  316. break;
  317. if (i >= BITRATE_TABLE_SIZE)
  318. printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
  319. priv->ndev->name, val);
  320. *bitrate = bitrate_table[i].bitrate * 100000;
  321. break;
  322. default:
  323. BUG();
  324. }
  325. return err;
  326. }
  327. /* Set fixed AP address */
  328. int __orinoco_hw_set_wap(struct orinoco_private *priv)
  329. {
  330. int roaming_flag;
  331. int err = 0;
  332. hermes_t *hw = &priv->hw;
  333. switch (priv->firmware_type) {
  334. case FIRMWARE_TYPE_AGERE:
  335. /* not supported */
  336. break;
  337. case FIRMWARE_TYPE_INTERSIL:
  338. if (priv->bssid_fixed)
  339. roaming_flag = 2;
  340. else
  341. roaming_flag = 1;
  342. err = hermes_write_wordrec(hw, USER_BAP,
  343. HERMES_RID_CNFROAMINGMODE,
  344. roaming_flag);
  345. break;
  346. case FIRMWARE_TYPE_SYMBOL:
  347. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  348. HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
  349. &priv->desired_bssid);
  350. break;
  351. }
  352. return err;
  353. }
  354. /* Change the WEP keys and/or the current keys. Can be called
  355. * either from __orinoco_hw_setup_enc() or directly from
  356. * orinoco_ioctl_setiwencode(). In the later case the association
  357. * with the AP is not broken (if the firmware can handle it),
  358. * which is needed for 802.1x implementations. */
  359. int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
  360. {
  361. hermes_t *hw = &priv->hw;
  362. int err = 0;
  363. switch (priv->firmware_type) {
  364. case FIRMWARE_TYPE_AGERE:
  365. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  366. HERMES_RID_CNFWEPKEYS_AGERE,
  367. &priv->keys);
  368. if (err)
  369. return err;
  370. err = hermes_write_wordrec(hw, USER_BAP,
  371. HERMES_RID_CNFTXKEY_AGERE,
  372. priv->tx_key);
  373. if (err)
  374. return err;
  375. break;
  376. case FIRMWARE_TYPE_INTERSIL:
  377. case FIRMWARE_TYPE_SYMBOL:
  378. {
  379. int keylen;
  380. int i;
  381. /* Force uniform key length to work around
  382. * firmware bugs */
  383. keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
  384. if (keylen > LARGE_KEY_SIZE) {
  385. printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
  386. priv->ndev->name, priv->tx_key, keylen);
  387. return -E2BIG;
  388. }
  389. /* Write all 4 keys */
  390. for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
  391. err = hermes_write_ltv(hw, USER_BAP,
  392. HERMES_RID_CNFDEFAULTKEY0 + i,
  393. HERMES_BYTES_TO_RECLEN(keylen),
  394. priv->keys[i].data);
  395. if (err)
  396. return err;
  397. }
  398. /* Write the index of the key used in transmission */
  399. err = hermes_write_wordrec(hw, USER_BAP,
  400. HERMES_RID_CNFWEPDEFAULTKEYID,
  401. priv->tx_key);
  402. if (err)
  403. return err;
  404. }
  405. break;
  406. }
  407. return 0;
  408. }
  409. int __orinoco_hw_setup_enc(struct orinoco_private *priv)
  410. {
  411. hermes_t *hw = &priv->hw;
  412. int err = 0;
  413. int master_wep_flag;
  414. int auth_flag;
  415. int enc_flag;
  416. /* Setup WEP keys for WEP and WPA */
  417. if (priv->encode_alg)
  418. __orinoco_hw_setup_wepkeys(priv);
  419. if (priv->wep_restrict)
  420. auth_flag = HERMES_AUTH_SHARED_KEY;
  421. else
  422. auth_flag = HERMES_AUTH_OPEN;
  423. if (priv->wpa_enabled)
  424. enc_flag = 2;
  425. else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
  426. enc_flag = 1;
  427. else
  428. enc_flag = 0;
  429. switch (priv->firmware_type) {
  430. case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
  431. if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
  432. /* Enable the shared-key authentication. */
  433. err = hermes_write_wordrec(hw, USER_BAP,
  434. HERMES_RID_CNFAUTHENTICATION_AGERE,
  435. auth_flag);
  436. }
  437. err = hermes_write_wordrec(hw, USER_BAP,
  438. HERMES_RID_CNFWEPENABLED_AGERE,
  439. enc_flag);
  440. if (err)
  441. return err;
  442. if (priv->has_wpa) {
  443. /* Set WPA key management */
  444. err = hermes_write_wordrec(hw, USER_BAP,
  445. HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
  446. priv->key_mgmt);
  447. if (err)
  448. return err;
  449. }
  450. break;
  451. case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
  452. case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
  453. if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
  454. if (priv->wep_restrict ||
  455. (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
  456. master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
  457. HERMES_WEP_EXCL_UNENCRYPTED;
  458. else
  459. master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
  460. err = hermes_write_wordrec(hw, USER_BAP,
  461. HERMES_RID_CNFAUTHENTICATION,
  462. auth_flag);
  463. if (err)
  464. return err;
  465. } else
  466. master_wep_flag = 0;
  467. if (priv->iw_mode == IW_MODE_MONITOR)
  468. master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
  469. /* Master WEP setting : on/off */
  470. err = hermes_write_wordrec(hw, USER_BAP,
  471. HERMES_RID_CNFWEPFLAGS_INTERSIL,
  472. master_wep_flag);
  473. if (err)
  474. return err;
  475. break;
  476. }
  477. return 0;
  478. }
  479. /* key must be 32 bytes, including the tx and rx MIC keys.
  480. * rsc must be 8 bytes
  481. * tsc must be 8 bytes or NULL
  482. */
  483. int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
  484. u8 *key, u8 *rsc, u8 *tsc)
  485. {
  486. struct {
  487. __le16 idx;
  488. u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
  489. u8 key[TKIP_KEYLEN];
  490. u8 tx_mic[MIC_KEYLEN];
  491. u8 rx_mic[MIC_KEYLEN];
  492. u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
  493. } __attribute__ ((packed)) buf;
  494. int ret;
  495. int err;
  496. int k;
  497. u16 xmitting;
  498. key_idx &= 0x3;
  499. if (set_tx)
  500. key_idx |= 0x8000;
  501. buf.idx = cpu_to_le16(key_idx);
  502. memcpy(buf.key, key,
  503. sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
  504. if (rsc == NULL)
  505. memset(buf.rsc, 0, sizeof(buf.rsc));
  506. else
  507. memcpy(buf.rsc, rsc, sizeof(buf.rsc));
  508. if (tsc == NULL) {
  509. memset(buf.tsc, 0, sizeof(buf.tsc));
  510. buf.tsc[4] = 0x10;
  511. } else {
  512. memcpy(buf.tsc, tsc, sizeof(buf.tsc));
  513. }
  514. /* Wait upto 100ms for tx queue to empty */
  515. for (k = 100; k > 0; k--) {
  516. udelay(1000);
  517. ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
  518. &xmitting);
  519. if (ret || !xmitting)
  520. break;
  521. }
  522. if (k == 0)
  523. ret = -ETIMEDOUT;
  524. err = HERMES_WRITE_RECORD(hw, USER_BAP,
  525. HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
  526. &buf);
  527. return ret ? ret : err;
  528. }
  529. int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
  530. {
  531. hermes_t *hw = &priv->hw;
  532. int err;
  533. memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
  534. err = hermes_write_wordrec(hw, USER_BAP,
  535. HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
  536. key_idx);
  537. if (err)
  538. printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
  539. priv->ndev->name, err, key_idx);
  540. return err;
  541. }
  542. int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
  543. struct dev_addr_list *mc_list,
  544. int mc_count, int promisc)
  545. {
  546. hermes_t *hw = &priv->hw;
  547. int err = 0;
  548. if (promisc != priv->promiscuous) {
  549. err = hermes_write_wordrec(hw, USER_BAP,
  550. HERMES_RID_CNFPROMISCUOUSMODE,
  551. promisc);
  552. if (err) {
  553. printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
  554. priv->ndev->name, err);
  555. } else
  556. priv->promiscuous = promisc;
  557. }
  558. /* If we're not in promiscuous mode, then we need to set the
  559. * group address if either we want to multicast, or if we were
  560. * multicasting and want to stop */
  561. if (!promisc && (mc_count || priv->mc_count)) {
  562. struct dev_mc_list *p = mc_list;
  563. struct hermes_multicast mclist;
  564. int i;
  565. for (i = 0; i < mc_count; i++) {
  566. /* paranoia: is list shorter than mc_count? */
  567. BUG_ON(!p);
  568. /* paranoia: bad address size in list? */
  569. BUG_ON(p->dmi_addrlen != ETH_ALEN);
  570. memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
  571. p = p->next;
  572. }
  573. if (p)
  574. printk(KERN_WARNING "%s: Multicast list is "
  575. "longer than mc_count\n", priv->ndev->name);
  576. err = hermes_write_ltv(hw, USER_BAP,
  577. HERMES_RID_CNFGROUPADDRESSES,
  578. HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
  579. &mclist);
  580. if (err)
  581. printk(KERN_ERR "%s: Error %d setting multicast list.\n",
  582. priv->ndev->name, err);
  583. else
  584. priv->mc_count = mc_count;
  585. }
  586. return err;
  587. }
  588. /* Return : < 0 -> error code ; >= 0 -> length */
  589. int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
  590. char buf[IW_ESSID_MAX_SIZE+1])
  591. {
  592. hermes_t *hw = &priv->hw;
  593. int err = 0;
  594. struct hermes_idstring essidbuf;
  595. char *p = (char *)(&essidbuf.val);
  596. int len;
  597. unsigned long flags;
  598. if (orinoco_lock(priv, &flags) != 0)
  599. return -EBUSY;
  600. if (strlen(priv->desired_essid) > 0) {
  601. /* We read the desired SSID from the hardware rather
  602. than from priv->desired_essid, just in case the
  603. firmware is allowed to change it on us. I'm not
  604. sure about this */
  605. /* My guess is that the OWNSSID should always be whatever
  606. * we set to the card, whereas CURRENT_SSID is the one that
  607. * may change... - Jean II */
  608. u16 rid;
  609. *active = 1;
  610. rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
  611. HERMES_RID_CNFDESIREDSSID;
  612. err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
  613. NULL, &essidbuf);
  614. if (err)
  615. goto fail_unlock;
  616. } else {
  617. *active = 0;
  618. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
  619. sizeof(essidbuf), NULL, &essidbuf);
  620. if (err)
  621. goto fail_unlock;
  622. }
  623. len = le16_to_cpu(essidbuf.len);
  624. BUG_ON(len > IW_ESSID_MAX_SIZE);
  625. memset(buf, 0, IW_ESSID_MAX_SIZE);
  626. memcpy(buf, p, len);
  627. err = len;
  628. fail_unlock:
  629. orinoco_unlock(priv, &flags);
  630. return err;
  631. }
  632. int orinoco_hw_get_freq(struct orinoco_private *priv)
  633. {
  634. hermes_t *hw = &priv->hw;
  635. int err = 0;
  636. u16 channel;
  637. int freq = 0;
  638. unsigned long flags;
  639. if (orinoco_lock(priv, &flags) != 0)
  640. return -EBUSY;
  641. err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
  642. &channel);
  643. if (err)
  644. goto out;
  645. /* Intersil firmware 1.3.5 returns 0 when the interface is down */
  646. if (channel == 0) {
  647. err = -EBUSY;
  648. goto out;
  649. }
  650. if ((channel < 1) || (channel > NUM_CHANNELS)) {
  651. printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
  652. priv->ndev->name, channel);
  653. err = -EBUSY;
  654. goto out;
  655. }
  656. freq = ieee80211_dsss_chan_to_freq(channel);
  657. out:
  658. orinoco_unlock(priv, &flags);
  659. if (err > 0)
  660. err = -EBUSY;
  661. return err ? err : freq;
  662. }
  663. int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
  664. int *numrates, s32 *rates, int max)
  665. {
  666. hermes_t *hw = &priv->hw;
  667. struct hermes_idstring list;
  668. unsigned char *p = (unsigned char *)&list.val;
  669. int err = 0;
  670. int num;
  671. int i;
  672. unsigned long flags;
  673. if (orinoco_lock(priv, &flags) != 0)
  674. return -EBUSY;
  675. err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
  676. sizeof(list), NULL, &list);
  677. orinoco_unlock(priv, &flags);
  678. if (err)
  679. return err;
  680. num = le16_to_cpu(list.len);
  681. *numrates = num;
  682. num = min(num, max);
  683. for (i = 0; i < num; i++)
  684. rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
  685. return 0;
  686. }