airo.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:169k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. for(i=0; (int)statsLabels[i]!=-1 &&
  2.     i*4<stats.len; i++){
  3. if (!statsLabels[i]) continue;
  4. if (j+strlen(statsLabels[i])+16>4096) {
  5. printk(KERN_WARNING
  6.        "airo: Potentially disasterous buffer overflow averted!n");
  7. break;
  8. }
  9. j+=sprintf(data->rbuffer+j, "%s: %dn", statsLabels[i], vals[i]);
  10. }
  11. if (i*4>=stats.len){
  12. printk(KERN_WARNING
  13.        "airo: Got a short ridn");
  14. }
  15. data->readlen = j;
  16. return 0;
  17. }
  18. static int get_dec_u16( char *buffer, int *start, int limit ) {
  19. u16 value;
  20. int valid = 0;
  21. for( value = 0; buffer[*start] >= '0' &&
  22.      buffer[*start] <= '9' &&
  23.      *start < limit; (*start)++ ) {
  24. valid = 1;
  25. value *= 10;
  26. value += buffer[*start] - '0';
  27. }
  28. if ( !valid ) return -1;
  29. return value;
  30. }
  31. static void proc_config_on_close( struct inode *inode, struct file *file ) {
  32. struct proc_data *data = file->private_data;
  33. struct proc_dir_entry *dp = PDE(inode);
  34. struct net_device *dev = dp->data;
  35. struct airo_info *ai = dev->priv;
  36. Resp rsp;
  37. char *line;
  38. int need_reset = 0;
  39. if ( !data->writelen ) return;
  40. readConfigRid(ai);
  41. line = data->wbuffer;
  42. while( line[0] ) {
  43. /*** Mode processing */
  44. if ( !strncmp( line, "Mode: ", 6 ) ) {
  45. line += 6;
  46. if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
  47. need_reset = 1;
  48. ai->config.rmode &= 0xfe00;
  49. ai->flags &= ~FLAG_802_11;
  50. ai->config.opmode &= 0xFF00;
  51. if ( line[0] == 'a' ) {
  52. ai->config.opmode |= 0;
  53. } else {
  54. ai->config.opmode |= 1;
  55. if ( line[0] == 'r' ) {
  56. ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
  57. ai->flags |= FLAG_802_11;
  58. } else if ( line[0] == 'y' ) {
  59. ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
  60. ai->flags |= FLAG_802_11;
  61. } else if ( line[0] == 'l' )
  62. ai->config.rmode |= RXMODE_LANMON;
  63. }
  64. ai->need_commit = 1;
  65. }
  66. /*** Radio status */
  67. else if (!strncmp(line,"Radio: ", 7)) {
  68. line += 7;
  69. if (!strncmp(line,"off",3)) {
  70. ai->flags |= FLAG_RADIO_OFF;
  71. } else {
  72. ai->flags &= ~FLAG_RADIO_OFF;
  73. }
  74. }
  75. /*** NodeName processing */
  76. else if ( !strncmp( line, "NodeName: ", 10 ) ) {
  77. int j;
  78. line += 10;
  79. memset( ai->config.nodeName, 0, 16 );
  80. /* Do the name, assume a space between the mode and node name */
  81. for( j = 0; j < 16 && line[j] != 'n'; j++ ) {
  82. ai->config.nodeName[j] = line[j];
  83. }
  84. ai->need_commit = 1;
  85. }
  86. /*** PowerMode processing */
  87. else if ( !strncmp( line, "PowerMode: ", 11 ) ) {
  88. line += 11;
  89. if ( !strncmp( line, "PSPCAM", 6 ) ) {
  90. ai->config.powerSaveMode = POWERSAVE_PSPCAM;
  91. ai->need_commit = 1;
  92. } else if ( !strncmp( line, "PSP", 3 ) ) {
  93. ai->config.powerSaveMode = POWERSAVE_PSP;
  94. ai->need_commit = 1;
  95. } else {
  96. ai->config.powerSaveMode = POWERSAVE_CAM;
  97. ai->need_commit = 1;
  98. }
  99. } else if ( !strncmp( line, "DataRates: ", 11 ) ) {
  100. int v, i = 0, k = 0; /* i is index into line,
  101. k is index to rates */
  102. line += 11;
  103. while((v = get_dec_u16(line, &i, 3))!=-1) {
  104. ai->config.rates[k++] = (u8)v;
  105. line += i + 1;
  106. i = 0;
  107. }
  108. ai->need_commit = 1;
  109. } else if ( !strncmp( line, "Channel: ", 9 ) ) {
  110. int v, i = 0;
  111. line += 9;
  112. v = get_dec_u16(line, &i, i+3);
  113. if ( v != -1 ) {
  114. ai->config.channelSet = (u16)v;
  115. ai->need_commit = 1;
  116. }
  117. } else if ( !strncmp( line, "XmitPower: ", 11 ) ) {
  118. int v, i = 0;
  119. line += 11;
  120. v = get_dec_u16(line, &i, i+3);
  121. if ( v != -1 ) {
  122. ai->config.txPower = (u16)v;
  123. ai->need_commit = 1;
  124. }
  125. } else if ( !strncmp( line, "WEP: ", 5 ) ) {
  126. line += 5;
  127. switch( line[0] ) {
  128. case 's':
  129. ai->config.authType = (u16)AUTH_SHAREDKEY;
  130. break;
  131. case 'e':
  132. ai->config.authType = (u16)AUTH_ENCRYPT;
  133. break;
  134. default:
  135. ai->config.authType = (u16)AUTH_OPEN;
  136. break;
  137. }
  138. ai->need_commit = 1;
  139. } else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) {
  140. int v, i = 0;
  141. line += 16;
  142. v = get_dec_u16(line, &i, 3);
  143. v = (v<0) ? 0 : ((v>255) ? 255 : v);
  144. ai->config.longRetryLimit = (u16)v;
  145. ai->need_commit = 1;
  146. } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) {
  147. int v, i = 0;
  148. line += 17;
  149. v = get_dec_u16(line, &i, 3);
  150. v = (v<0) ? 0 : ((v>255) ? 255 : v);
  151. ai->config.shortRetryLimit = (u16)v;
  152. ai->need_commit = 1;
  153. } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) {
  154. int v, i = 0;
  155. line += 14;
  156. v = get_dec_u16(line, &i, 4);
  157. v = (v<0) ? 0 : ((v>2312) ? 2312 : v);
  158. ai->config.rtsThres = (u16)v;
  159. ai->need_commit = 1;
  160. } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
  161. int v, i = 0;
  162. line += 16;
  163. v = get_dec_u16(line, &i, 5);
  164. v = (v<0) ? 0 : v;
  165. ai->config.txLifetime = (u16)v;
  166. ai->need_commit = 1;
  167. } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) {
  168. int v, i = 0;
  169. line += 16;
  170. v = get_dec_u16(line, &i, 5);
  171. v = (v<0) ? 0 : v;
  172. ai->config.rxLifetime = (u16)v;
  173. ai->need_commit = 1;
  174. } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) {
  175. ai->config.txDiversity =
  176. (line[13]=='l') ? 1 :
  177. ((line[13]=='r')? 2: 3);
  178. ai->need_commit = 1;
  179. } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) {
  180. ai->config.rxDiversity =
  181. (line[13]=='l') ? 1 :
  182. ((line[13]=='r')? 2: 3);
  183. ai->need_commit = 1;
  184. } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) {
  185. int v, i = 0;
  186. line += 15;
  187. v = get_dec_u16(line, &i, 4);
  188. v = (v<256) ? 256 : ((v>2312) ? 2312 : v);
  189. v = v & 0xfffe; /* Make sure its even */
  190. ai->config.fragThresh = (u16)v;
  191. ai->need_commit = 1;
  192. } else if (!strncmp(line, "Modulation: ", 12)) {
  193. line += 12;
  194. switch(*line) {
  195. case 'd':  ai->config.modulation=MOD_DEFAULT; ai->need_commit=1; break;
  196. case 'c':  ai->config.modulation=MOD_CCK; ai->need_commit=1; break;
  197. case 'm':  ai->config.modulation=MOD_MOK; ai->need_commit=1; break;
  198. default:
  199. printk( KERN_WARNING "airo: Unknown modulationn" );
  200. }
  201. } else if (!strncmp(line, "Preamble: ", 10)) {
  202. line += 10;
  203. switch(*line) {
  204. case 'a': ai->config.preamble=PREAMBLE_AUTO; ai->need_commit=1; break;
  205. case 'l': ai->config.preamble=PREAMBLE_LONG; ai->need_commit=1; break;
  206. case 's': ai->config.preamble=PREAMBLE_SHORT; ai->need_commit=1; break;
  207.         default: printk(KERN_WARNING "airo: Unknown preamblen");
  208. }
  209. } else {
  210. printk( KERN_WARNING "Couldn't figure out %sn", line );
  211. }
  212. while( line[0] && line[0] != 'n' ) line++;
  213. if ( line[0] ) line++;
  214. }
  215. disable_MAC(ai);
  216. if (need_reset) {
  217. APListRid APList_rid;
  218. SsidRid SSID_rid;
  219. readAPListRid(ai, &APList_rid);
  220. readSsidRid(ai, &SSID_rid);
  221. reset_airo_card(dev);
  222. disable_MAC(ai);
  223. writeSsidRid(ai, &SSID_rid);
  224. writeAPListRid(ai, &APList_rid);
  225. }
  226. writeConfigRid(ai);
  227. enable_MAC(ai, &rsp);
  228. if (need_reset)
  229. airo_set_promisc(ai);
  230. }
  231. static char *get_rmode(u16 mode) {
  232.         switch(mode&0xff) {
  233.         case RXMODE_RFMON:  return "rfmon";
  234.         case RXMODE_RFMON_ANYBSS:  return "yna (any) bss rfmon";
  235.         case RXMODE_LANMON:  return "lanmon";
  236.         }
  237.         return "ESS";
  238. }
  239. static int proc_config_open( struct inode *inode, struct file *file ) {
  240. struct proc_data *data;
  241. struct proc_dir_entry *dp = PDE(inode);
  242. struct net_device *dev = dp->data;
  243. struct airo_info *ai = dev->priv;
  244. int i;
  245. MOD_INC_USE_COUNT;
  246. if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
  247. return -ENOMEM;
  248. memset(file->private_data, 0, sizeof(struct proc_data));
  249. data = (struct proc_data *)file->private_data;
  250. if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
  251. kfree (file->private_data);
  252. return -ENOMEM;
  253. }
  254. if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
  255. kfree (data->rbuffer);
  256. kfree (file->private_data);
  257. return -ENOMEM;
  258. }
  259. memset( data->wbuffer, 0, 2048 );
  260. data->maxwritelen = 2048;
  261. data->on_close = proc_config_on_close;
  262. readConfigRid(ai);
  263. i = sprintf( data->rbuffer,
  264.      "Mode: %sn"
  265.      "Radio: %sn"
  266.      "NodeName: %-16sn"
  267.      "PowerMode: %sn"
  268.      "DataRates: %d %d %d %d %d %d %d %dn"
  269.      "Channel: %dn"
  270.      "XmitPower: %dn",
  271.      (ai->config.opmode & 0xFF) == 0 ? "adhoc" :
  272.      (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode):
  273.      (ai->config.opmode & 0xFF) == 2 ? "AP" :
  274.      (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error",
  275.      ai->flags&FLAG_RADIO_OFF ? "off" : "on",
  276.      ai->config.nodeName,
  277.      ai->config.powerSaveMode == 0 ? "CAM" :
  278.      ai->config.powerSaveMode == 1 ? "PSP" :
  279.      ai->config.powerSaveMode == 2 ? "PSPCAM" : "Error",
  280.      (int)ai->config.rates[0],
  281.      (int)ai->config.rates[1],
  282.      (int)ai->config.rates[2],
  283.      (int)ai->config.rates[3],
  284.      (int)ai->config.rates[4],
  285.      (int)ai->config.rates[5],
  286.      (int)ai->config.rates[6],
  287.      (int)ai->config.rates[7],
  288.      (int)ai->config.channelSet,
  289.      (int)ai->config.txPower
  290. );
  291. sprintf( data->rbuffer + i,
  292.  "LongRetryLimit: %dn"
  293.  "ShortRetryLimit: %dn"
  294.  "RTSThreshold: %dn"
  295.  "TXMSDULifetime: %dn"
  296.  "RXMSDULifetime: %dn"
  297.  "TXDiversity: %sn"
  298.  "RXDiversity: %sn"
  299.  "FragThreshold: %dn"
  300.  "WEP: %sn"
  301.  "Modulation: %sn"
  302.  "Preamble: %sn",
  303.  (int)ai->config.longRetryLimit,
  304.  (int)ai->config.shortRetryLimit,
  305.  (int)ai->config.rtsThres,
  306.  (int)ai->config.txLifetime,
  307.  (int)ai->config.rxLifetime,
  308.  ai->config.txDiversity == 1 ? "left" :
  309.  ai->config.txDiversity == 2 ? "right" : "both",
  310.  ai->config.rxDiversity == 1 ? "left" :
  311.  ai->config.rxDiversity == 2 ? "right" : "both",
  312.  (int)ai->config.fragThresh,
  313.  ai->config.authType == AUTH_ENCRYPT ? "encrypt" :
  314.  ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open",
  315.  ai->config.modulation == 0 ? "default" :
  316.  ai->config.modulation == MOD_CCK ? "cck" :
  317.  ai->config.modulation == MOD_MOK ? "mok" : "error",
  318.  ai->config.preamble == PREAMBLE_AUTO ? "auto" :
  319.  ai->config.preamble == PREAMBLE_LONG ? "long" :
  320.  ai->config.preamble == PREAMBLE_SHORT ? "short" : "error"
  321. );
  322. data->readlen = strlen( data->rbuffer );
  323. return 0;
  324. }
  325. static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
  326. struct proc_data *data = (struct proc_data *)file->private_data;
  327. struct proc_dir_entry *dp = PDE(inode);
  328. struct net_device *dev = dp->data;
  329. struct airo_info *ai = dev->priv;
  330. SsidRid SSID_rid;
  331. Resp rsp;
  332. int i;
  333. int offset = 0;
  334. if ( !data->writelen ) return;
  335. memset( &SSID_rid, 0, sizeof( SSID_rid ) );
  336. for( i = 0; i < 3; i++ ) {
  337. int j;
  338. for( j = 0; j+offset < data->writelen && j < 32 &&
  339.      data->wbuffer[offset+j] != 'n'; j++ ) {
  340. SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j];
  341. }
  342. if ( j == 0 ) break;
  343. SSID_rid.ssids[i].len = j;
  344. offset += j;
  345. while( data->wbuffer[offset] != 'n' &&
  346.        offset < data->writelen ) offset++;
  347. offset++;
  348. }
  349. disable_MAC(ai);
  350. writeSsidRid(ai, &SSID_rid);
  351. enable_MAC(ai, &rsp);
  352. }
  353. inline static u8 hexVal(char c) {
  354. if (c>='0' && c<='9') return c -= '0';
  355. if (c>='a' && c<='f') return c -= 'a'-10;
  356. if (c>='A' && c<='F') return c -= 'A'-10;
  357. return 0;
  358. }
  359. static void proc_APList_on_close( struct inode *inode, struct file *file ) {
  360. struct proc_data *data = (struct proc_data *)file->private_data;
  361. struct proc_dir_entry *dp = PDE(inode);
  362. struct net_device *dev = dp->data;
  363. struct airo_info *ai = dev->priv;
  364. APListRid APList_rid;
  365. Resp rsp;
  366. int i;
  367. if ( !data->writelen ) return;
  368. memset( &APList_rid, 0, sizeof(APList_rid) );
  369. APList_rid.len = sizeof(APList_rid);
  370. for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
  371. int j;
  372. for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
  373. switch(j%3) {
  374. case 0:
  375. APList_rid.ap[i][j/3]=
  376. hexVal(data->wbuffer[j+i*6*3])<<4;
  377. break;
  378. case 1:
  379. APList_rid.ap[i][j/3]|=
  380. hexVal(data->wbuffer[j+i*6*3]);
  381. break;
  382. }
  383. }
  384. }
  385. disable_MAC(ai);
  386. writeAPListRid(ai, &APList_rid);
  387. enable_MAC(ai, &rsp);
  388. }
  389. /* This function wraps PC4500_writerid with a MAC disable */
  390. static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
  391. int len ) {
  392. int rc;
  393. Resp rsp;
  394. disable_MAC(ai);
  395. rc = PC4500_writerid(ai, rid, rid_data, len);
  396. enable_MAC(ai, &rsp);
  397. return rc;
  398. }
  399. /* Returns the length of the key at the index.  If index == 0xffff
  400.  * the index of the transmit key is returned.  If the key doesn't exist,
  401.  * -1 will be returned.
  402.  */
  403. static int get_wep_key(struct airo_info *ai, u16 index) {
  404. WepKeyRid wkr;
  405. int rc;
  406. u16 lastindex;
  407. rc = readWepKeyRid(ai, &wkr, 1);
  408. if (rc == SUCCESS) do {
  409. lastindex = wkr.kindex;
  410. if (wkr.kindex == index) {
  411. if (index == 0xffff) {
  412. return wkr.mac[0];
  413. }
  414. return wkr.klen;
  415. }
  416. readWepKeyRid(ai, &wkr, 0);
  417. } while(lastindex != wkr.kindex);
  418. return -1;
  419. }
  420. static int set_wep_key(struct airo_info *ai, u16 index,
  421.        const char *key, u16 keylen, int perm ) {
  422. static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
  423. WepKeyRid wkr;
  424. memset(&wkr, 0, sizeof(wkr));
  425. if (keylen == 0) {
  426. // We are selecting which key to use
  427. wkr.len = sizeof(wkr);
  428. wkr.kindex = 0xffff;
  429. wkr.mac[0] = (char)index;
  430. if (perm) printk(KERN_INFO "Setting transmit key to %dn", index);
  431. if (perm) ai->defindex = (char)index;
  432. } else {
  433. // We are actually setting the key
  434. wkr.len = sizeof(wkr);
  435. wkr.kindex = index;
  436. wkr.klen = keylen;
  437. memcpy( wkr.key, key, keylen );
  438. memcpy( wkr.mac, macaddr, ETH_ALEN );
  439. printk(KERN_INFO "Setting key %dn", index);
  440. }
  441. writeWepKeyRid(ai, &wkr, perm);
  442. return 0;
  443. }
  444. static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
  445. struct proc_data *data;
  446. struct proc_dir_entry *dp = PDE(inode);
  447. struct net_device *dev = dp->data;
  448. struct airo_info *ai = dev->priv;
  449. int i;
  450. char key[16];
  451. u16 index = 0;
  452. int j = 0;
  453. memset(key, 0, sizeof(key));
  454. data = (struct proc_data *)file->private_data;
  455. if ( !data->writelen ) return;
  456. if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
  457.     (data->wbuffer[1] == ' ' || data->wbuffer[1] == 'n')) {
  458. index = data->wbuffer[0] - '0';
  459. if (data->wbuffer[1] == 'n') {
  460. set_wep_key(ai, index, 0, 0, 1);
  461. return;
  462. }
  463. j = 2;
  464. } else {
  465. printk(KERN_ERR "airo:  WepKey passed invalid key indexn");
  466. return;
  467. }
  468. for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) {
  469. switch(i%3) {
  470. case 0:
  471. key[i/3] = hexVal(data->wbuffer[i+j])<<4;
  472. break;
  473. case 1:
  474. key[i/3] |= hexVal(data->wbuffer[i+j]);
  475. break;
  476. }
  477. }
  478. set_wep_key(ai, index, key, i/3, 1);
  479. }
  480. static int proc_wepkey_open( struct inode *inode, struct file *file ) {
  481. struct proc_data *data;
  482. struct proc_dir_entry *dp = PDE(inode);
  483. struct net_device *dev = dp->data;
  484. struct airo_info *ai = dev->priv;
  485. char *ptr;
  486. WepKeyRid wkr;
  487. u16 lastindex;
  488. int j=0;
  489. int rc;
  490. MOD_INC_USE_COUNT;
  491. if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
  492. return -ENOMEM;
  493. memset(file->private_data, 0, sizeof(struct proc_data));
  494. memset(&wkr, 0, sizeof(wkr));
  495. data = (struct proc_data *)file->private_data;
  496. if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) {
  497. kfree (file->private_data);
  498. return -ENOMEM;
  499. }
  500. memset(data->rbuffer, 0, 180);
  501. data->writelen = 0;
  502. data->maxwritelen = 80;
  503. if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) {
  504. kfree (data->rbuffer);
  505. kfree (file->private_data);
  506. return -ENOMEM;
  507. }
  508. memset( data->wbuffer, 0, 80 );
  509. data->on_close = proc_wepkey_on_close;
  510. ptr = data->rbuffer;
  511. strcpy(ptr, "No wep keysn");
  512. rc = readWepKeyRid(ai, &wkr, 1);
  513. if (rc == SUCCESS) do {
  514. lastindex = wkr.kindex;
  515. if (wkr.kindex == 0xffff) {
  516. j += sprintf(ptr+j, "Tx key = %dn",
  517.      (int)wkr.mac[0]);
  518. } else {
  519. j += sprintf(ptr+j, "Key %d set with length = %dn",
  520.      (int)wkr.kindex, (int)wkr.klen);
  521. }
  522. readWepKeyRid(ai, &wkr, 0);
  523. } while((lastindex != wkr.kindex) && (j < 180-30));
  524. data->readlen = strlen( data->rbuffer );
  525. return 0;
  526. }
  527. static int proc_SSID_open( struct inode *inode, struct file *file ) {
  528. struct proc_data *data;
  529. struct proc_dir_entry *dp = PDE(inode);
  530. struct net_device *dev = dp->data;
  531. struct airo_info *ai = dev->priv;
  532. int i;
  533. char *ptr;
  534. SsidRid SSID_rid;
  535. MOD_INC_USE_COUNT;
  536. if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
  537. return -ENOMEM;
  538. memset(file->private_data, 0, sizeof(struct proc_data));
  539. data = (struct proc_data *)file->private_data;
  540. if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
  541. kfree (file->private_data);
  542. return -ENOMEM;
  543. }
  544. data->writelen = 0;
  545. data->maxwritelen = 33*3;
  546. if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) {
  547. kfree (data->rbuffer);
  548. kfree (file->private_data);
  549. return -ENOMEM;
  550. }
  551. memset( data->wbuffer, 0, 33*3 );
  552. data->on_close = proc_SSID_on_close;
  553. readSsidRid(ai, &SSID_rid);
  554. ptr = data->rbuffer;
  555. for( i = 0; i < 3; i++ ) {
  556. int j;
  557. if ( !SSID_rid.ssids[i].len ) break;
  558. for( j = 0; j < 32 &&
  559.      j < SSID_rid.ssids[i].len &&
  560.      SSID_rid.ssids[i].ssid[j]; j++ ) {
  561. *ptr++ = SSID_rid.ssids[i].ssid[j];
  562. }
  563. *ptr++ = 'n';
  564. }
  565. *ptr = '';
  566. data->readlen = strlen( data->rbuffer );
  567. return 0;
  568. }
  569. static int proc_APList_open( struct inode *inode, struct file *file ) {
  570. struct proc_data *data;
  571. struct proc_dir_entry *dp = PDE(inode);
  572. struct net_device *dev = dp->data;
  573. struct airo_info *ai = dev->priv;
  574. int i;
  575. char *ptr;
  576. APListRid APList_rid;
  577. MOD_INC_USE_COUNT;
  578. if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
  579. return -ENOMEM;
  580. memset(file->private_data, 0, sizeof(struct proc_data));
  581. data = (struct proc_data *)file->private_data;
  582. if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
  583. kfree (file->private_data);
  584. return -ENOMEM;
  585. }
  586. data->writelen = 0;
  587. data->maxwritelen = 4*6*3;
  588. if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
  589. kfree (data->rbuffer);
  590. kfree (file->private_data);
  591. return -ENOMEM;
  592. }
  593. memset( data->wbuffer, 0, data->maxwritelen );
  594. data->on_close = proc_APList_on_close;
  595. readAPListRid(ai, &APList_rid);
  596. ptr = data->rbuffer;
  597. for( i = 0; i < 4; i++ ) {
  598. // We end when we find a zero MAC
  599. if ( !*(int*)APList_rid.ap[i] &&
  600.      !*(int*)&APList_rid.ap[i][2]) break;
  601. ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02xn",
  602.        (int)APList_rid.ap[i][0],
  603.        (int)APList_rid.ap[i][1],
  604.        (int)APList_rid.ap[i][2],
  605.        (int)APList_rid.ap[i][3],
  606.        (int)APList_rid.ap[i][4],
  607.        (int)APList_rid.ap[i][5]);
  608. }
  609. if (i==0) ptr += sprintf(ptr, "Not using specific APsn");
  610. *ptr = '';
  611. data->readlen = strlen( data->rbuffer );
  612. return 0;
  613. }
  614. static int proc_BSSList_open( struct inode *inode, struct file *file ) {
  615. struct proc_data *data;
  616. struct proc_dir_entry *dp = PDE(inode);
  617. struct net_device *dev = dp->data;
  618. struct airo_info *ai = dev->priv;
  619. char *ptr;
  620. BSSListRid BSSList_rid;
  621. int rc;
  622. /* If doLoseSync is not 1, we won't do a Lose Sync */
  623. int doLoseSync = -1;
  624. MOD_INC_USE_COUNT;
  625. if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
  626. return -ENOMEM;
  627. memset(file->private_data, 0, sizeof(struct proc_data));
  628. data = (struct proc_data *)file->private_data;
  629. if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
  630. kfree (file->private_data);
  631. return -ENOMEM;
  632. }
  633. data->writelen = 0;
  634. data->maxwritelen = 0;
  635. data->wbuffer = 0;
  636. data->on_close = 0;
  637. if (file->f_mode & FMODE_WRITE) {
  638. if (!(file->f_mode & FMODE_READ)) {
  639. Cmd cmd;
  640. Resp rsp;
  641. memset(&cmd, 0, sizeof(cmd));
  642. cmd.cmd=CMD_LISTBSS;
  643. if (down_interruptible(&ai->sem))
  644. return -ERESTARTSYS;
  645. issuecommand(ai, &cmd, &rsp);
  646. up(&ai->sem);
  647. data->readlen = 0;
  648. return 0;
  649. }
  650. doLoseSync = 1;
  651. }
  652. ptr = data->rbuffer;
  653. /* There is a race condition here if there are concurrent opens.
  654.            Since it is a rare condition, we'll just live with it, otherwise
  655.            we have to add a spin lock... */
  656. rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
  657. while(rc == 0 && BSSList_rid.index != 0xffff) {
  658. ptr += sprintf(ptr, "%02x:%02x:%02x:%02x:%02x:%02x %*s rssi = %d",
  659. (int)BSSList_rid.bssid[0],
  660. (int)BSSList_rid.bssid[1],
  661. (int)BSSList_rid.bssid[2],
  662. (int)BSSList_rid.bssid[3],
  663. (int)BSSList_rid.bssid[4],
  664. (int)BSSList_rid.bssid[5],
  665. (int)BSSList_rid.ssidLen,
  666. BSSList_rid.ssid,
  667. (int)BSSList_rid.rssi);
  668. ptr += sprintf(ptr, " channel = %d %s %s %s %sn",
  669. (int)BSSList_rid.dsChannel,
  670. BSSList_rid.cap & CAP_ESS ? "ESS" : "",
  671. BSSList_rid.cap & CAP_IBSS ? "adhoc" : "",
  672. BSSList_rid.cap & CAP_PRIVACY ? "wep" : "",
  673. BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : "");
  674. rc = readBSSListRid(ai, 0, &BSSList_rid);
  675. }
  676. *ptr = '';
  677. data->readlen = strlen( data->rbuffer );
  678. return 0;
  679. }
  680. static int proc_close( struct inode *inode, struct file *file )
  681. {
  682. struct proc_data *data = (struct proc_data *)file->private_data;
  683. if ( data->on_close != NULL ) data->on_close( inode, file );
  684. MOD_DEC_USE_COUNT;
  685. if ( data->rbuffer ) kfree( data->rbuffer );
  686. if ( data->wbuffer ) kfree( data->wbuffer );
  687. kfree( data );
  688. return 0;
  689. }
  690. static struct net_device_list {
  691. struct net_device *dev;
  692. struct net_device_list *next;
  693. } *airo_devices = 0;
  694. /* Since the card doesn't automatically switch to the right WEP mode,
  695.    we will make it do it.  If the card isn't associated, every secs we
  696.    will switch WEP modes to see if that will help.  If the card is
  697.    associated we will check every minute to see if anything has
  698.    changed. */
  699. static void timer_func( u_long data ) {
  700. struct net_device *dev = (struct net_device*)data;
  701. struct airo_info *apriv = dev->priv;
  702. u16 linkstat = IN4500(apriv, LINKSTAT);
  703. Resp rsp;
  704. if (!(apriv->flags & FLAG_FLASHING) && (linkstat != 0x400)) {
  705. /* We don't have a link so try changing the authtype */
  706. if (down_trylock(&apriv->sem) != 0) {
  707. apriv->timer.expires = RUN_AT(1);
  708. add_timer(&apriv->timer);
  709. return;
  710. }
  711. __set_bit(FLAG_LOCKED, &apriv->flags);
  712. readConfigRid(apriv);
  713. disable_MAC(apriv);
  714. switch(apriv->config.authType) {
  715. case AUTH_ENCRYPT:
  716. /* So drop to OPEN */
  717. apriv->config.authType = AUTH_OPEN;
  718. break;
  719. case AUTH_SHAREDKEY:
  720. if (apriv->keyindex < auto_wep) {
  721. set_wep_key(apriv, apriv->keyindex, 0, 0, 0);
  722. apriv->config.authType = AUTH_SHAREDKEY;
  723. apriv->keyindex++;
  724. } else {
  725.         /* Drop to ENCRYPT */
  726. apriv->keyindex = 0;
  727. set_wep_key(apriv, apriv->defindex, 0, 0, 0);
  728. apriv->config.authType = AUTH_ENCRYPT;
  729. }
  730. break;
  731. default:  /* We'll escalate to SHAREDKEY */
  732. apriv->config.authType = AUTH_SHAREDKEY;
  733. }
  734. apriv->need_commit = 1;
  735. writeConfigRid(apriv);
  736. enable_MAC(apriv, &rsp);
  737. clear_bit(FLAG_LOCKED, &apriv->flags);
  738. up(&apriv->sem);
  739. /* Schedule check to see if the change worked */
  740. apriv->timer.expires = RUN_AT(HZ*3);
  741. add_timer(&apriv->timer);
  742. }
  743. }
  744. static int add_airo_dev( struct net_device *dev ) {
  745. struct net_device_list *node = kmalloc( sizeof( *node ), GFP_KERNEL );
  746. if ( !node )
  747. return -ENOMEM;
  748. if ( auto_wep ) {
  749. struct airo_info *apriv=dev->priv;
  750. struct timer_list *timer = &apriv->timer;
  751. timer->function = timer_func;
  752. timer->data = (u_long)dev;
  753. init_timer(timer);
  754. }
  755. node->dev = dev;
  756. node->next = airo_devices;
  757. airo_devices = node;
  758. return 0;
  759. }
  760. static void del_airo_dev( struct net_device *dev ) {
  761. struct net_device_list **p = &airo_devices;
  762. while( *p && ( (*p)->dev != dev ) )
  763. p = &(*p)->next;
  764. if ( *p && (*p)->dev == dev )
  765. *p = (*p)->next;
  766. }
  767. #ifdef CONFIG_PCI
  768. static int __devinit airo_pci_probe(struct pci_dev *pdev,
  769.     const struct pci_device_id *pent)
  770. {
  771. struct net_device *dev;
  772. dev = init_airo_card(pdev->irq, pdev->resource[2].start, 0);
  773. if (!dev)
  774. return -ENODEV;
  775. pci_set_drvdata(pdev, dev);
  776. return 0;
  777. }
  778. static void __devexit airo_pci_remove(struct pci_dev *pdev)
  779. {
  780. stop_airo_card(pci_get_drvdata(pdev), 1);
  781. }
  782. #endif
  783. static int __init airo_init_module( void )
  784. {
  785. int i, rc = 0, have_isa_dev = 0;
  786. airo_entry = create_proc_entry("aironet",
  787.        S_IFDIR | airo_perm,
  788.        proc_root_driver);
  789.         airo_entry->uid = proc_uid;
  790.         airo_entry->gid = proc_gid;
  791. for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
  792. printk( KERN_INFO
  793. "airo:  Trying to configure ISA adapter at irq=%d io=0x%xn",
  794. irq[i], io[i] );
  795. if (init_airo_card( irq[i], io[i], 0 ))
  796. have_isa_dev = 1;
  797. }
  798. #ifdef CONFIG_PCI
  799. printk( KERN_INFO "airo:  Probing for PCI adaptersn" );
  800. rc = pci_module_init(&airo_driver);
  801. printk( KERN_INFO "airo:  Finished probing for PCI adaptersn" );
  802. #endif
  803. /* Always exit with success, as we are a library module
  804.  * as well as a driver module
  805.  */
  806. return 0;
  807. }
  808. static void __exit airo_cleanup_module( void )
  809. {
  810. while( airo_devices ) {
  811. printk( KERN_INFO "airo: Unregistering %sn", airo_devices->dev->name );
  812. stop_airo_card( airo_devices->dev, 1 );
  813. }
  814. remove_proc_entry("aironet", proc_root_driver);
  815. }
  816. #ifdef WIRELESS_EXT
  817. /*
  818.  * Initial Wireless Extension code for Aironet driver by :
  819.  * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
  820.  * Conversion to new driver API by :
  821.  * Jean Tourrilhes <jt@hpl.hp.com> - HPL - 26 March 02
  822.  * Javier also did a good amount of work here, adding some new extensions
  823.  * and fixing my code. Let's just say that without him this code just
  824.  * would not work at all... - Jean II
  825.  */
  826. /*------------------------------------------------------------------*/
  827. /*
  828.  * Wireless Handler : get protocol name
  829.  */
  830. static int airo_get_name(struct net_device *dev,
  831.  struct iw_request_info *info,
  832.  char *cwrq,
  833.  char *extra)
  834. {
  835. strcpy(cwrq, "IEEE 802.11-DS");
  836. return 0;
  837. }
  838. /*------------------------------------------------------------------*/
  839. /*
  840.  * Wireless Handler : set frequency
  841.  */
  842. static int airo_set_freq(struct net_device *dev,
  843.  struct iw_request_info *info,
  844.  struct iw_freq *fwrq,
  845.  char *extra)
  846. {
  847. struct airo_info *local = dev->priv;
  848. int rc = -EINPROGRESS; /* Call commit handler */
  849. /* If setting by frequency, convert to a channel */
  850. if((fwrq->e == 1) &&
  851.    (fwrq->m >= (int) 2.412e8) &&
  852.    (fwrq->m <= (int) 2.487e8)) {
  853. int f = fwrq->m / 100000;
  854. int c = 0;
  855. while((c < 14) && (f != frequency_list[c]))
  856. c++;
  857. /* Hack to fall through... */
  858. fwrq->e = 0;
  859. fwrq->m = c + 1;
  860. }
  861. /* Setting by channel number */
  862. if((fwrq->m > 1000) || (fwrq->e > 0))
  863. rc = -EOPNOTSUPP;
  864. else {
  865. int channel = fwrq->m;
  866. /* We should do a better check than that,
  867.  * based on the card capability !!! */
  868. if((channel < 1) || (channel > 16)) {
  869. printk(KERN_DEBUG "%s: New channel value of %d is invalid!n", dev->name, fwrq->m);
  870. rc = -EINVAL;
  871. } else {
  872. /* Yes ! We can set it !!! */
  873. local->config.channelSet = (u16)(channel - 1);
  874. local->need_commit = 1;
  875. }
  876. }
  877. return rc;
  878. }
  879. /*------------------------------------------------------------------*/
  880. /*
  881.  * Wireless Handler : get frequency
  882.  */
  883. static int airo_get_freq(struct net_device *dev,
  884.  struct iw_request_info *info,
  885.  struct iw_freq *fwrq,
  886.  char *extra)
  887. {
  888. struct airo_info *local = dev->priv;
  889. StatusRid status_rid; /* Card status info */
  890. readStatusRid(local, &status_rid);
  891. /* Will return zero in infrastructure mode */
  892. #ifdef WEXT_USECHANNELS
  893. fwrq->m = ((int)status_rid.channel) + 1;
  894. fwrq->e = 0;
  895. #else
  896. {
  897. int f = (int)status_rid.channel;
  898. fwrq->m = frequency_list[f] * 100000;
  899. fwrq->e = 1;
  900. }
  901. #endif
  902. return 0;
  903. }
  904. /*------------------------------------------------------------------*/
  905. /*
  906.  * Wireless Handler : set ESSID
  907.  */
  908. static int airo_set_essid(struct net_device *dev,
  909.   struct iw_request_info *info,
  910.   struct iw_point *dwrq,
  911.   char *extra)
  912. {
  913. struct airo_info *local = dev->priv;
  914. Resp rsp;
  915. SsidRid SSID_rid; /* SSIDs */
  916. /* Reload the list of current SSID */
  917. readSsidRid(local, &SSID_rid);
  918. /* Check if we asked for `any' */
  919. if(dwrq->flags == 0) {
  920. /* Just send an empty SSID list */
  921. memset(&SSID_rid, 0, sizeof(SSID_rid));
  922. } else {
  923. int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  924. /* Check the size of the string */
  925. if(dwrq->length > IW_ESSID_MAX_SIZE+1) {
  926. return -E2BIG ;
  927. }
  928. /* Check if index is valid */
  929. if((index < 0) || (index >= 4)) {
  930. return -EINVAL;
  931. }
  932. /* Set the SSID */
  933. memset(SSID_rid.ssids[index].ssid, 0,
  934.        sizeof(SSID_rid.ssids[index].ssid));
  935. memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
  936. SSID_rid.ssids[index].len = dwrq->length - 1;
  937. }
  938. /* Write it to the card */
  939. disable_MAC(local);
  940. writeSsidRid(local, &SSID_rid);
  941. enable_MAC(local, &rsp);
  942. return 0;
  943. }
  944. /*------------------------------------------------------------------*/
  945. /*
  946.  * Wireless Handler : get ESSID
  947.  */
  948. static int airo_get_essid(struct net_device *dev,
  949.   struct iw_request_info *info,
  950.   struct iw_point *dwrq,
  951.   char *extra)
  952. {
  953. struct airo_info *local = dev->priv;
  954. StatusRid status_rid; /* Card status info */
  955. readStatusRid(local, &status_rid);
  956. /* Note : if dwrq->flags != 0, we should
  957.  * get the relevant SSID from the SSID list... */
  958. /* Get the current SSID */
  959. memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
  960. extra[status_rid.SSIDlen] = '';
  961. /* If none, we may want to get the one that was set */
  962. /* Push it out ! */
  963. dwrq->length = status_rid.SSIDlen + 1;
  964. dwrq->flags = 1; /* active */
  965. return 0;
  966. }
  967. /*------------------------------------------------------------------*/
  968. /*
  969.  * Wireless Handler : set AP address
  970.  */
  971. static int airo_set_wap(struct net_device *dev,
  972. struct iw_request_info *info,
  973. struct sockaddr *awrq,
  974. char *extra)
  975. {
  976. struct airo_info *local = dev->priv;
  977. Cmd cmd;
  978. Resp rsp;
  979. APListRid APList_rid;
  980. static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
  981. if (awrq->sa_family != ARPHRD_ETHER)
  982. return -EINVAL;
  983. else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
  984. memset(&cmd, 0, sizeof(cmd));
  985. cmd.cmd=CMD_LOSE_SYNC;
  986. if (down_interruptible(&local->sem))
  987. return -ERESTARTSYS;
  988. issuecommand(local, &cmd, &rsp);
  989. up(&local->sem);
  990. } else {
  991. memset(&APList_rid, 0, sizeof(APList_rid));
  992. APList_rid.len = sizeof(APList_rid);
  993. memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
  994. disable_MAC(local);
  995. writeAPListRid(local, &APList_rid);
  996. enable_MAC(local, &rsp);
  997. }
  998. return 0;
  999. }
  1000. /*------------------------------------------------------------------*/
  1001. /*
  1002.  * Wireless Handler : get AP address
  1003.  */
  1004. static int airo_get_wap(struct net_device *dev,
  1005. struct iw_request_info *info,
  1006. struct sockaddr *awrq,
  1007. char *extra)
  1008. {
  1009. struct airo_info *local = dev->priv;
  1010. StatusRid status_rid; /* Card status info */
  1011. readStatusRid(local, &status_rid);
  1012. /* Tentative. This seems to work, wow, I'm lucky !!! */
  1013. memcpy(awrq->sa_data, status_rid.bssid[0], ETH_ALEN);
  1014. awrq->sa_family = ARPHRD_ETHER;
  1015. return 0;
  1016. }
  1017. /*------------------------------------------------------------------*/
  1018. /*
  1019.  * Wireless Handler : set Nickname
  1020.  */
  1021. static int airo_set_nick(struct net_device *dev,
  1022.  struct iw_request_info *info,
  1023.  struct iw_point *dwrq,
  1024.  char *extra)
  1025. {
  1026. struct airo_info *local = dev->priv;
  1027. /* Check the size of the string */
  1028. if(dwrq->length > 16 + 1) {
  1029. return -E2BIG;
  1030. }
  1031. memset(local->config.nodeName, 0, sizeof(local->config.nodeName));
  1032. memcpy(local->config.nodeName, extra, dwrq->length);
  1033. local->need_commit = 1;
  1034. return -EINPROGRESS; /* Call commit handler */
  1035. }
  1036. /*------------------------------------------------------------------*/
  1037. /*
  1038.  * Wireless Handler : get Nickname
  1039.  */
  1040. static int airo_get_nick(struct net_device *dev,
  1041.  struct iw_request_info *info,
  1042.  struct iw_point *dwrq,
  1043.  char *extra)
  1044. {
  1045. struct airo_info *local = dev->priv;
  1046. strncpy(extra, local->config.nodeName, 16);
  1047. extra[16] = '';
  1048. dwrq->length = strlen(extra) + 1;
  1049. return 0;
  1050. }
  1051. /*------------------------------------------------------------------*/
  1052. /*
  1053.  * Wireless Handler : set Bit-Rate
  1054.  */
  1055. static int airo_set_rate(struct net_device *dev,
  1056.  struct iw_request_info *info,
  1057.  struct iw_param *vwrq,
  1058.  char *extra)
  1059. {
  1060. struct airo_info *local = dev->priv;
  1061. CapabilityRid cap_rid; /* Card capability info */
  1062. u8 brate = 0;
  1063. int i;
  1064. /* First : get a valid bit rate value */
  1065. readCapabilityRid(local, &cap_rid);
  1066. /* Which type of value ? */
  1067. if((vwrq->value < 8) && (vwrq->value >= 0)) {
  1068. /* Setting by rate index */
  1069. /* Find value in the magic rate table */
  1070. brate = cap_rid.supportedRates[vwrq->value];
  1071. } else {
  1072. /* Setting by frequency value */
  1073. u8 normvalue = (u8) (vwrq->value/500000);
  1074. /* Check if rate is valid */
  1075. for(i = 0 ; i < 8 ; i++) {
  1076. if(normvalue == cap_rid.supportedRates[i]) {
  1077. brate = normvalue;
  1078. break;
  1079. }
  1080. }
  1081. }
  1082. /* -1 designed the max rate (mostly auto mode) */
  1083. if(vwrq->value == -1) {
  1084. /* Get the highest available rate */
  1085. for(i = 0 ; i < 8 ; i++) {
  1086. if(cap_rid.supportedRates[i] == 0)
  1087. break;
  1088. }
  1089. if(i != 0)
  1090. brate = cap_rid.supportedRates[i - 1];
  1091. }
  1092. /* Check that it is valid */
  1093. if(brate == 0) {
  1094. return -EINVAL;
  1095. }
  1096. /* Now, check if we want a fixed or auto value */
  1097. if(vwrq->fixed == 0) {
  1098. /* Fill all the rates up to this max rate */
  1099. memset(local->config.rates, 0, 8);
  1100. for(i = 0 ; i < 8 ; i++) {
  1101. local->config.rates[i] = cap_rid.supportedRates[i];
  1102. if(local->config.rates[i] == brate)
  1103. break;
  1104. }
  1105. } else {
  1106. /* Fixed mode */
  1107. /* One rate, fixed */
  1108. memset(local->config.rates, 0, 8);
  1109. local->config.rates[0] = brate;
  1110. }
  1111. local->need_commit = 1;
  1112. return -EINPROGRESS; /* Call commit handler */
  1113. }
  1114. /*------------------------------------------------------------------*/
  1115. /*
  1116.  * Wireless Handler : get Bit-Rate
  1117.  */
  1118. static int airo_get_rate(struct net_device *dev,
  1119.  struct iw_request_info *info,
  1120.  struct iw_param *vwrq,
  1121.  char *extra)
  1122. {
  1123. struct airo_info *local = dev->priv;
  1124. StatusRid status_rid; /* Card status info */
  1125. readStatusRid(local, &status_rid);
  1126. vwrq->value = status_rid.currentXmitRate * 500000;
  1127. /* If more than one rate, set auto */
  1128. vwrq->fixed = (local->config.rates[1] == 0);
  1129. return 0;
  1130. }
  1131. /*------------------------------------------------------------------*/
  1132. /*
  1133.  * Wireless Handler : set RTS threshold
  1134.  */
  1135. static int airo_set_rts(struct net_device *dev,
  1136. struct iw_request_info *info,
  1137. struct iw_param *vwrq,
  1138. char *extra)
  1139. {
  1140. struct airo_info *local = dev->priv;
  1141. int rthr = vwrq->value;
  1142. if(vwrq->disabled)
  1143. rthr = 2312;
  1144. if((rthr < 0) || (rthr > 2312)) {
  1145. return -EINVAL;
  1146. }
  1147. local->config.rtsThres = rthr;
  1148. local->need_commit = 1;
  1149. return -EINPROGRESS; /* Call commit handler */
  1150. }
  1151. /*------------------------------------------------------------------*/
  1152. /*
  1153.  * Wireless Handler : get RTS threshold
  1154.  */
  1155. static int airo_get_rts(struct net_device *dev,
  1156. struct iw_request_info *info,
  1157. struct iw_param *vwrq,
  1158. char *extra)
  1159. {
  1160. struct airo_info *local = dev->priv;
  1161. vwrq->value = local->config.rtsThres;
  1162. vwrq->disabled = (vwrq->value >= 2312);
  1163. vwrq->fixed = 1;
  1164. return 0;
  1165. }
  1166. /*------------------------------------------------------------------*/
  1167. /*
  1168.  * Wireless Handler : set Fragmentation threshold
  1169.  */
  1170. static int airo_set_frag(struct net_device *dev,
  1171.  struct iw_request_info *info,
  1172.  struct iw_param *vwrq,
  1173.  char *extra)
  1174. {
  1175. struct airo_info *local = dev->priv;
  1176. int fthr = vwrq->value;
  1177. if(vwrq->disabled)
  1178. fthr = 2312;
  1179. if((fthr < 256) || (fthr > 2312)) {
  1180. return -EINVAL;
  1181. }
  1182. fthr &= ~0x1; /* Get an even value - is it really needed ??? */
  1183. local->config.fragThresh = (u16)fthr;
  1184. local->need_commit = 1;
  1185. return -EINPROGRESS; /* Call commit handler */
  1186. }
  1187. /*------------------------------------------------------------------*/
  1188. /*
  1189.  * Wireless Handler : get Fragmentation threshold
  1190.  */
  1191. static int airo_get_frag(struct net_device *dev,
  1192.  struct iw_request_info *info,
  1193.  struct iw_param *vwrq,
  1194.  char *extra)
  1195. {
  1196. struct airo_info *local = dev->priv;
  1197. vwrq->value = local->config.fragThresh;
  1198. vwrq->disabled = (vwrq->value >= 2312);
  1199. vwrq->fixed = 1;
  1200. return 0;
  1201. }
  1202. /*------------------------------------------------------------------*/
  1203. /*
  1204.  * Wireless Handler : set Mode of Operation
  1205.  */
  1206. static int airo_set_mode(struct net_device *dev,
  1207.  struct iw_request_info *info,
  1208.  __u32 *uwrq,
  1209.  char *extra)
  1210. {
  1211. struct airo_info *local = dev->priv;
  1212. switch(*uwrq) {
  1213. case IW_MODE_ADHOC:
  1214. local->config.opmode &= 0xFF00;
  1215. local->config.opmode |= MODE_STA_IBSS;
  1216. break;
  1217. case IW_MODE_INFRA:
  1218. local->config.opmode &= 0xFF00;
  1219. local->config.opmode |= MODE_STA_ESS;
  1220. break;
  1221. case IW_MODE_MASTER:
  1222. local->config.opmode &= 0xFF00;
  1223. local->config.opmode |= MODE_AP;
  1224. break;
  1225. case IW_MODE_REPEAT:
  1226. local->config.opmode &= 0xFF00;
  1227. local->config.opmode |= MODE_AP_RPTR;
  1228. break;
  1229. default:
  1230. return -EINVAL;
  1231. }
  1232. local->need_commit = 1;
  1233. return -EINPROGRESS; /* Call commit handler */
  1234. }
  1235. /*------------------------------------------------------------------*/
  1236. /*
  1237.  * Wireless Handler : get Mode of Operation
  1238.  */
  1239. static int airo_get_mode(struct net_device *dev,
  1240.  struct iw_request_info *info,
  1241.  __u32 *uwrq,
  1242.  char *extra)
  1243. {
  1244. struct airo_info *local = dev->priv;
  1245. /* If not managed, assume it's ad-hoc */
  1246. switch (local->config.opmode & 0xFF) {
  1247. case MODE_STA_ESS:
  1248. *uwrq = IW_MODE_INFRA;
  1249. break;
  1250. case MODE_AP:
  1251. *uwrq = IW_MODE_MASTER;
  1252. break;
  1253. case MODE_AP_RPTR:
  1254. *uwrq = IW_MODE_REPEAT;
  1255. break;
  1256. default:
  1257. *uwrq = IW_MODE_ADHOC;
  1258. }
  1259. return 0;
  1260. }
  1261. /*------------------------------------------------------------------*/
  1262. /*
  1263.  * Wireless Handler : set Encryption Key
  1264.  */
  1265. static int airo_set_encode(struct net_device *dev,
  1266.    struct iw_request_info *info,
  1267.    struct iw_point *dwrq,
  1268.    char *extra)
  1269. {
  1270. struct airo_info *local = dev->priv;
  1271. CapabilityRid cap_rid; /* Card capability info */
  1272. /* Is WEP supported ? */
  1273. readCapabilityRid(local, &cap_rid);
  1274. /* Older firmware doesn't support this...
  1275. if(!(cap_rid.softCap & 2)) {
  1276. return -EOPNOTSUPP;
  1277. } */
  1278. /* Basic checking: do we have a key to set ?
  1279.  * Note : with the new API, it's impossible to get a NULL pointer.
  1280.  * Therefore, we need to check a key size == 0 instead.
  1281.  * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
  1282.  * when no key is present (only change flags), but older versions
  1283.  * don't do it. - Jean II */
  1284. if (dwrq->length > 0) {
  1285. wep_key_t key;
  1286. int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1287. int current_index = get_wep_key(local, 0xffff);
  1288. /* Check the size of the key */
  1289. if (dwrq->length > MAX_KEY_SIZE) {
  1290. return -EINVAL;
  1291. }
  1292. /* Check the index (none -> use current) */
  1293. if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1))
  1294. index = current_index;
  1295. /* Set the length */
  1296. if (dwrq->length > MIN_KEY_SIZE)
  1297. key.len = MAX_KEY_SIZE;
  1298. else
  1299. if (dwrq->length > 0)
  1300. key.len = MIN_KEY_SIZE;
  1301. else
  1302. /* Disable the key */
  1303. key.len = 0;
  1304. /* Check if the key is not marked as invalid */
  1305. if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
  1306. /* Cleanup */
  1307. memset(key.key, 0, MAX_KEY_SIZE);
  1308. /* Copy the key in the driver */
  1309. memcpy(key.key, extra, dwrq->length);
  1310. /* Send the key to the card */
  1311. set_wep_key(local, index, key.key, key.len, 1);
  1312. }
  1313. /* WE specify that if a valid key is set, encryption
  1314.  * should be enabled (user may turn it off later)
  1315.  * This is also how "iwconfig ethX key on" works */
  1316. if((index == current_index) && (key.len > 0) &&
  1317.    (local->config.authType == AUTH_OPEN)) {
  1318. local->config.authType = AUTH_ENCRYPT;
  1319. local->need_commit = 1;
  1320. }
  1321. } else {
  1322. /* Do we want to just set the transmit key index ? */
  1323. int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1324. if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) {
  1325. set_wep_key(local, index, 0, 0, 1);
  1326. } else
  1327. /* Don't complain if only change the mode */
  1328. if(!dwrq->flags & IW_ENCODE_MODE) {
  1329. return -EINVAL;
  1330. }
  1331. }
  1332. /* Read the flags */
  1333. if(dwrq->flags & IW_ENCODE_DISABLED)
  1334. local->config.authType = AUTH_OPEN; // disable encryption
  1335. if(dwrq->flags & IW_ENCODE_RESTRICTED)
  1336. local->config.authType = AUTH_SHAREDKEY; // Only Both
  1337. if(dwrq->flags & IW_ENCODE_OPEN)
  1338. local->config.authType = AUTH_ENCRYPT; // Only Wep
  1339. /* Commit the changes to flags if needed */
  1340. if(dwrq->flags & IW_ENCODE_MODE)
  1341. local->need_commit = 1;
  1342. return -EINPROGRESS; /* Call commit handler */
  1343. }
  1344. /*------------------------------------------------------------------*/
  1345. /*
  1346.  * Wireless Handler : get Encryption Key
  1347.  */
  1348. static int airo_get_encode(struct net_device *dev,
  1349.    struct iw_request_info *info,
  1350.    struct iw_point *dwrq,
  1351.    char *extra)
  1352. {
  1353. struct airo_info *local = dev->priv;
  1354. int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
  1355. CapabilityRid cap_rid; /* Card capability info */
  1356. /* Is it supported ? */
  1357. readCapabilityRid(local, &cap_rid);
  1358. if(!(cap_rid.softCap & 2)) {
  1359. return -EOPNOTSUPP;
  1360. }
  1361. /* Check encryption mode */
  1362. switch(local->config.authType) {
  1363. case AUTH_ENCRYPT:
  1364. dwrq->flags = IW_ENCODE_OPEN;
  1365. break;
  1366. case AUTH_SHAREDKEY:
  1367. dwrq->flags = IW_ENCODE_RESTRICTED;
  1368. break;
  1369. default:
  1370. case AUTH_OPEN:
  1371. dwrq->flags = IW_ENCODE_DISABLED;
  1372. break;
  1373. }
  1374. /* We can't return the key, so set the proper flag and return zero */
  1375. dwrq->flags |= IW_ENCODE_NOKEY;
  1376. memset(extra, 0, 16);
  1377. /* Which key do we want ? -1 -> tx index */
  1378. if((index < 0) || (index >= (cap_rid.softCap & 0x80) ? 4 : 1))
  1379. index = get_wep_key(local, 0xffff);
  1380. dwrq->flags |= index + 1;
  1381. /* Copy the key to the user buffer */
  1382. dwrq->length = get_wep_key(local, index);
  1383. if (dwrq->length > 16) {
  1384. dwrq->length=0;
  1385. }
  1386. return 0;
  1387. }
  1388. /*------------------------------------------------------------------*/
  1389. /*
  1390.  * Wireless Handler : set Tx-Power
  1391.  */
  1392. static int airo_set_txpow(struct net_device *dev,
  1393.   struct iw_request_info *info,
  1394.   struct iw_param *vwrq,
  1395.   char *extra)
  1396. {
  1397. struct airo_info *local = dev->priv;
  1398. CapabilityRid cap_rid; /* Card capability info */
  1399. int i;
  1400. int rc = -EINVAL;
  1401. readCapabilityRid(local, &cap_rid);
  1402. if (vwrq->disabled) {
  1403. local->flags |= FLAG_RADIO_OFF;
  1404. local->need_commit = 1;
  1405. return -EINPROGRESS; /* Call commit handler */
  1406. }
  1407. if (vwrq->flags != IW_TXPOW_MWATT) {
  1408. return -EINVAL;
  1409. }
  1410. local->flags &= ~FLAG_RADIO_OFF;
  1411. for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
  1412. if ((vwrq->value==cap_rid.txPowerLevels[i])) {
  1413. local->config.txPower = vwrq->value;
  1414. local->need_commit = 1;
  1415. rc = -EINPROGRESS; /* Call commit handler */
  1416. break;
  1417. }
  1418. return rc;
  1419. }
  1420. /*------------------------------------------------------------------*/
  1421. /*
  1422.  * Wireless Handler : get Tx-Power
  1423.  */
  1424. static int airo_get_txpow(struct net_device *dev,
  1425.   struct iw_request_info *info,
  1426.   struct iw_param *vwrq,
  1427.   char *extra)
  1428. {
  1429. struct airo_info *local = dev->priv;
  1430. vwrq->value = local->config.txPower;
  1431. vwrq->fixed = 1; /* No power control */
  1432. vwrq->disabled = (local->flags & FLAG_RADIO_OFF);
  1433. vwrq->flags = IW_TXPOW_MWATT;
  1434. return 0;
  1435. }
  1436. /*------------------------------------------------------------------*/
  1437. /*
  1438.  * Wireless Handler : set Retry limits
  1439.  */
  1440. static int airo_set_retry(struct net_device *dev,
  1441.   struct iw_request_info *info,
  1442.   struct iw_param *vwrq,
  1443.   char *extra)
  1444. {
  1445. struct airo_info *local = dev->priv;
  1446. int rc = -EINVAL;
  1447. if(vwrq->disabled) {
  1448. return -EINVAL;
  1449. }
  1450. if(vwrq->flags & IW_RETRY_LIMIT) {
  1451. if(vwrq->flags & IW_RETRY_MAX)
  1452. local->config.longRetryLimit = vwrq->value;
  1453. else if (vwrq->flags & IW_RETRY_MIN)
  1454. local->config.shortRetryLimit = vwrq->value;
  1455. else {
  1456. /* No modifier : set both */
  1457. local->config.longRetryLimit = vwrq->value;
  1458. local->config.shortRetryLimit = vwrq->value;
  1459. }
  1460. local->need_commit = 1;
  1461. rc = -EINPROGRESS; /* Call commit handler */
  1462. }
  1463. if(vwrq->flags & IW_RETRY_LIFETIME) {
  1464. local->config.txLifetime = vwrq->value / 1024;
  1465. local->need_commit = 1;
  1466. rc = -EINPROGRESS; /* Call commit handler */
  1467. }
  1468. return rc;
  1469. }
  1470. /*------------------------------------------------------------------*/
  1471. /*
  1472.  * Wireless Handler : get Retry limits
  1473.  */
  1474. static int airo_get_retry(struct net_device *dev,
  1475.   struct iw_request_info *info,
  1476.   struct iw_param *vwrq,
  1477.   char *extra)
  1478. {
  1479. struct airo_info *local = dev->priv;
  1480. vwrq->disabled = 0;      /* Can't be disabled */
  1481. /* Note : by default, display the min retry number */
  1482. if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
  1483. vwrq->flags = IW_RETRY_LIFETIME;
  1484. vwrq->value = (int)local->config.txLifetime * 1024;
  1485. } else if((vwrq->flags & IW_RETRY_MAX)) {
  1486. vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
  1487. vwrq->value = (int)local->config.longRetryLimit;
  1488. } else {
  1489. vwrq->flags = IW_RETRY_LIMIT;
  1490. vwrq->value = (int)local->config.shortRetryLimit;
  1491. if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
  1492. vwrq->flags |= IW_RETRY_MIN;
  1493. }
  1494. return 0;
  1495. }
  1496. /*------------------------------------------------------------------*/
  1497. /*
  1498.  * Wireless Handler : get range info
  1499.  */
  1500. static int airo_get_range(struct net_device *dev,
  1501.   struct iw_request_info *info,
  1502.   struct iw_point *dwrq,
  1503.   char *extra)
  1504. {
  1505. struct airo_info *local = dev->priv;
  1506. struct iw_range *range = (struct iw_range *) extra;
  1507. CapabilityRid cap_rid; /* Card capability info */
  1508. int i;
  1509. int k;
  1510. readCapabilityRid(local, &cap_rid);
  1511. dwrq->length = sizeof(struct iw_range);
  1512. memset(range, 0, sizeof(range));
  1513. range->min_nwid = 0x0000;
  1514. range->max_nwid = 0x0000;
  1515. range->num_channels = 14;
  1516. /* Should be based on cap_rid.country to give only
  1517.  * what the current card support */
  1518. k = 0;
  1519. for(i = 0; i < 14; i++) {
  1520. range->freq[k].i = i + 1; /* List index */
  1521. range->freq[k].m = frequency_list[i] * 100000;
  1522. range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
  1523. }
  1524. range->num_frequency = k;
  1525. /* Hum... Should put the right values there */
  1526. range->max_qual.qual = 10;
  1527. range->max_qual.level = 0x100 - 120; /* -120 dBm */
  1528. range->max_qual.noise = 0;
  1529. range->sensitivity = 65535;
  1530. for(i = 0 ; i < 8 ; i++) {
  1531. range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
  1532. if(range->bitrate[i] == 0)
  1533. break;
  1534. }
  1535. range->num_bitrates = i;
  1536. /* Set an indication of the max TCP throughput
  1537.  * in bit/s that we can expect using this interface.
  1538.  * May be use for QoS stuff... Jean II */
  1539. if(i > 2)
  1540. range->throughput = 5000 * 1000;
  1541. else
  1542. range->throughput = 1500 * 1000;
  1543. range->min_rts = 0;
  1544. range->max_rts = 2312;
  1545. range->min_frag = 256;
  1546. range->max_frag = 2312;
  1547. if(cap_rid.softCap & 2) {
  1548. // WEP: RC4 40 bits
  1549. range->encoding_size[0] = 5;
  1550. // RC4 ~128 bits
  1551. if (cap_rid.softCap & 0x100) {
  1552. range->encoding_size[1] = 13;
  1553. range->num_encoding_sizes = 2;
  1554. } else
  1555. range->num_encoding_sizes = 1;
  1556. range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
  1557. } else {
  1558. range->num_encoding_sizes = 0;
  1559. range->max_encoding_tokens = 0;
  1560. }
  1561. range->min_pmp = 0;
  1562. range->max_pmp = 5000000; /* 5 secs */
  1563. range->min_pmt = 0;
  1564. range->max_pmt = 65535 * 1024; /* ??? */
  1565. range->pmp_flags = IW_POWER_PERIOD;
  1566. range->pmt_flags = IW_POWER_TIMEOUT;
  1567. range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
  1568. /* Transmit Power - values are in mW */
  1569. for(i = 0 ; i < 8 ; i++) {
  1570. range->txpower[i] = cap_rid.txPowerLevels[i];
  1571. if(range->txpower[i] == 0)
  1572. break;
  1573. }
  1574. range->num_txpower = i;
  1575. range->txpower_capa = IW_TXPOW_MWATT;
  1576. range->we_version_source = 12;
  1577. range->we_version_compiled = WIRELESS_EXT;
  1578. range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
  1579. range->retry_flags = IW_RETRY_LIMIT;
  1580. range->r_time_flags = IW_RETRY_LIFETIME;
  1581. range->min_retry = 1;
  1582. range->max_retry = 65535;
  1583. range->min_r_time = 1024;
  1584. range->max_r_time = 65535 * 1024;
  1585. /* Experimental measurements - boundary 11/5.5 Mb/s */
  1586. /* Note : with or without the (local->rssi), results
  1587.  * are somewhat different. - Jean II */
  1588. range->avg_qual.qual = 6;
  1589. if (local->rssi)
  1590. range->avg_qual.level = 186; /* -70 dBm */
  1591. else
  1592. range->avg_qual.level = 176; /* -80 dBm */
  1593. range->avg_qual.noise = 0;
  1594. return 0;
  1595. }
  1596. /*------------------------------------------------------------------*/
  1597. /*
  1598.  * Wireless Handler : set Power Management
  1599.  */
  1600. static int airo_set_power(struct net_device *dev,
  1601.   struct iw_request_info *info,
  1602.   struct iw_param *vwrq,
  1603.   char *extra)
  1604. {
  1605. struct airo_info *local = dev->priv;
  1606. if (vwrq->disabled) {
  1607. if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
  1608. return -EINVAL;
  1609. }
  1610. local->config.powerSaveMode = POWERSAVE_CAM;
  1611. local->config.rmode &= 0xFF00;
  1612. local->config.rmode |= RXMODE_BC_MC_ADDR;
  1613. local->need_commit = 1;
  1614. return -EINPROGRESS; /* Call commit handler */
  1615. }
  1616. if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
  1617. local->config.fastListenDelay = (vwrq->value + 500) / 1024;
  1618. local->config.powerSaveMode = POWERSAVE_PSPCAM;
  1619. local->need_commit = 1;
  1620. } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
  1621. local->config.fastListenInterval = local->config.listenInterval = (vwrq->value + 500) / 1024;
  1622. local->config.powerSaveMode = POWERSAVE_PSPCAM;
  1623. local->need_commit = 1;
  1624. }
  1625. switch (vwrq->flags & IW_POWER_MODE) {
  1626. case IW_POWER_UNICAST_R:
  1627. if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
  1628. return -EINVAL;
  1629. }
  1630. local->config.rmode &= 0xFF00;
  1631. local->config.rmode |= RXMODE_ADDR;
  1632. local->need_commit = 1;
  1633. break;
  1634. case IW_POWER_ALL_R:
  1635. if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
  1636. return -EINVAL;
  1637. }
  1638. local->config.rmode &= 0xFF00;
  1639. local->config.rmode |= RXMODE_BC_MC_ADDR;
  1640. local->need_commit = 1;
  1641. case IW_POWER_ON:
  1642. break;
  1643. default:
  1644. return -EINVAL;
  1645. }
  1646. // Note : we may want to factor local->need_commit here
  1647. // Note2 : may also want to factor RXMODE_RFMON test
  1648. return -EINPROGRESS; /* Call commit handler */
  1649. }
  1650. /*------------------------------------------------------------------*/
  1651. /*
  1652.  * Wireless Handler : get Power Management
  1653.  */
  1654. static int airo_get_power(struct net_device *dev,
  1655.   struct iw_request_info *info,
  1656.   struct iw_param *vwrq,
  1657.   char *extra)
  1658. {
  1659. struct airo_info *local = dev->priv;
  1660. int mode = local->config.powerSaveMode;
  1661. if ((vwrq->disabled = (mode == POWERSAVE_CAM)))
  1662. return 0;
  1663. if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
  1664. vwrq->value = (int)local->config.fastListenDelay * 1024;
  1665. vwrq->flags = IW_POWER_TIMEOUT;
  1666. } else {
  1667. vwrq->value = (int)local->config.fastListenInterval * 1024;
  1668. vwrq->flags = IW_POWER_PERIOD;
  1669. }
  1670. if ((local->config.rmode & 0xFF) == RXMODE_ADDR)
  1671. vwrq->flags |= IW_POWER_UNICAST_R;
  1672. else
  1673. vwrq->flags |= IW_POWER_ALL_R;
  1674. return 0;
  1675. }
  1676. /*------------------------------------------------------------------*/
  1677. /*
  1678.  * Wireless Handler : set Sensitivity
  1679.  */
  1680. static int airo_set_sens(struct net_device *dev,
  1681.  struct iw_request_info *info,
  1682.  struct iw_param *vwrq,
  1683.  char *extra)
  1684. {
  1685. struct airo_info *local = dev->priv;
  1686. local->config.rssiThreshold = vwrq->disabled ? RSSI_DEFAULT : vwrq->value;
  1687. local->need_commit = 1;
  1688. return -EINPROGRESS; /* Call commit handler */
  1689. }
  1690. /*------------------------------------------------------------------*/
  1691. /*
  1692.  * Wireless Handler : get Sensitivity
  1693.  */
  1694. static int airo_get_sens(struct net_device *dev,
  1695.  struct iw_request_info *info,
  1696.  struct iw_param *vwrq,
  1697.  char *extra)
  1698. {
  1699. struct airo_info *local = dev->priv;
  1700. vwrq->value = local->config.rssiThreshold;
  1701. vwrq->disabled = (vwrq->value == 0);
  1702. vwrq->fixed = 1;
  1703. return 0;
  1704. }
  1705. /*------------------------------------------------------------------*/
  1706. /*
  1707.  * Wireless Handler : get AP List
  1708.  * Note : this is deprecated in favor of IWSCAN
  1709.  */
  1710. static int airo_get_aplist(struct net_device *dev,
  1711.    struct iw_request_info *info,
  1712.    struct iw_point *dwrq,
  1713.    char *extra)
  1714. {
  1715. struct airo_info *local = dev->priv;
  1716. struct sockaddr *address = (struct sockaddr *) extra;
  1717. struct iw_quality qual[IW_MAX_AP];
  1718. BSSListRid BSSList;
  1719. int i;
  1720. int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
  1721. for (i = 0; i < IW_MAX_AP; i++) {
  1722. if (readBSSListRid(local, loseSync, &BSSList))
  1723. break;
  1724. loseSync = 0;
  1725. memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
  1726. address[i].sa_family = ARPHRD_ETHER;
  1727. if (local->rssi)
  1728. qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
  1729. else
  1730. qual[i].level = (BSSList.rssi + 321) / 2;
  1731. qual[i].qual = qual[i].noise = 0;
  1732. qual[i].updated = 2;
  1733. if (BSSList.index == 0xffff)
  1734. break;
  1735. }
  1736. if (!i) {
  1737. StatusRid status_rid; /* Card status info */
  1738. readStatusRid(local, &status_rid);
  1739. for (i = 0;
  1740.      i < min(IW_MAX_AP, 4) &&
  1741.      (status_rid.bssid[i][0]
  1742.       & status_rid.bssid[i][1]
  1743.       & status_rid.bssid[i][2]
  1744.       & status_rid.bssid[i][3]
  1745.       & status_rid.bssid[i][4]
  1746.       & status_rid.bssid[i][5])!=-1 &&
  1747.      (status_rid.bssid[i][0]
  1748.       | status_rid.bssid[i][1]
  1749.       | status_rid.bssid[i][2]
  1750.       | status_rid.bssid[i][3]
  1751.       | status_rid.bssid[i][4]
  1752.       | status_rid.bssid[i][5]);
  1753.      i++) {
  1754. memcpy(address[i].sa_data,
  1755.        status_rid.bssid[i], ETH_ALEN);
  1756. address[i].sa_family = ARPHRD_ETHER;
  1757. }
  1758. } else {
  1759. dwrq->flags = 1; /* Should be define'd */
  1760. memcpy(extra + sizeof(struct sockaddr)*i,
  1761.        &qual,  sizeof(struct iw_quality)*i);
  1762. }
  1763. dwrq->length = i;
  1764. return 0;
  1765. }
  1766. #if WIRELESS_EXT > 13
  1767. /*------------------------------------------------------------------*/
  1768. /*
  1769.  * Wireless Handler : Initiate Scan
  1770.  */
  1771. static int airo_set_scan(struct net_device *dev,
  1772.  struct iw_request_info *info,
  1773.  struct iw_param *vwrq,
  1774.  char *extra)
  1775. {
  1776. struct airo_info *ai = dev->priv;
  1777. Cmd cmd;
  1778. Resp rsp;
  1779. /* Note : you may have realised that, as this is a SET operation,
  1780.  * this is priviledged and therefore a normal user can't
  1781.  * perform scanning.
  1782.  * This is not an error, while the device perform scanning,
  1783.  * traffic doesn't flow, so it's a perfect DoS...
  1784.  * Jean II */
  1785. /* Initiate a scan command */
  1786. memset(&cmd, 0, sizeof(cmd));
  1787. cmd.cmd=CMD_LISTBSS;
  1788. if (down_interruptible(&ai->sem))
  1789. return -ERESTARTSYS;
  1790. issuecommand(ai, &cmd, &rsp);
  1791. ai->scan_timestamp = jiffies;
  1792. up(&ai->sem);
  1793. /* At this point, just return to the user. */
  1794. return 0;
  1795. }
  1796. /*------------------------------------------------------------------*/
  1797. /*
  1798.  * Translate scan data returned from the card to a card independant
  1799.  * format that the Wireless Tools will understand - Jean II
  1800.  */
  1801. static inline char *airo_translate_scan(struct net_device *dev,
  1802. char *current_ev,
  1803. char *end_buf,
  1804. BSSListRid *list)
  1805. {
  1806. struct airo_info *ai = dev->priv;
  1807. struct iw_event iwe; /* Temporary buffer */
  1808. u16 capabilities;
  1809. char * current_val; /* For rates */
  1810. int i;
  1811. /* First entry *MUST* be the AP MAC address */
  1812. iwe.cmd = SIOCGIWAP;
  1813. iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
  1814. memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN);
  1815. current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
  1816. /* Other entries will be displayed in the order we give them */
  1817. /* Add the ESSID */
  1818. iwe.u.data.length = list->ssidLen;
  1819. if(iwe.u.data.length > 32)
  1820. iwe.u.data.length = 32;
  1821. iwe.cmd = SIOCGIWESSID;
  1822. iwe.u.data.flags = 1;
  1823. current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
  1824. /* Add mode */
  1825. iwe.cmd = SIOCGIWMODE;
  1826. capabilities = le16_to_cpu(list->cap);
  1827. if(capabilities & (CAP_ESS | CAP_IBSS)) {
  1828. if(capabilities & CAP_ESS)
  1829. iwe.u.mode = IW_MODE_INFRA;
  1830. else
  1831. iwe.u.mode = IW_MODE_ADHOC;
  1832. current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
  1833. }
  1834. /* Add frequency */
  1835. iwe.cmd = SIOCGIWFREQ;
  1836. iwe.u.freq.m = le16_to_cpu(list->dsChannel);
  1837. iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
  1838. iwe.u.freq.e = 1;
  1839. current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
  1840. /* Add quality statistics */
  1841. iwe.cmd = IWEVQUAL;
  1842. if (ai->rssi)
  1843. iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm;
  1844. else
  1845. iwe.u.qual.level = (list->rssi + 321) / 2;
  1846. iwe.u.qual.noise = 0;
  1847. iwe.u.qual.qual = 0;
  1848. current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
  1849. /* Add encryption capability */
  1850. iwe.cmd = SIOCGIWENCODE;
  1851. if(capabilities & CAP_PRIVACY)
  1852. iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
  1853. else
  1854. iwe.u.data.flags = IW_ENCODE_DISABLED;
  1855. iwe.u.data.length = 0;
  1856. current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
  1857. /* Rate : stuffing multiple values in a single event require a bit
  1858.  * more of magic - Jean II */
  1859. current_val = current_ev + IW_EV_LCP_LEN;
  1860. iwe.cmd = SIOCGIWRATE;
  1861. /* Those two flags are ignored... */
  1862. iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
  1863. /* Max 8 values */
  1864. for(i = 0 ; i < 8 ; i++) {
  1865. /* NULL terminated */
  1866. if(list->rates[i] == 0)
  1867. break;
  1868. /* Bit rate given in 500 kb/s units (+ 0x80) */
  1869. iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000);
  1870. /* Add new value to event */
  1871. current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
  1872. }
  1873. /* Check if we added any event */
  1874. if((current_val - current_ev) > IW_EV_LCP_LEN)
  1875. current_ev = current_val;
  1876. /* The other data in the scan result are not really
  1877.  * interesting, so for now drop it - Jean II */
  1878. return current_ev;
  1879. }
  1880. /*------------------------------------------------------------------*/
  1881. /*
  1882.  * Wireless Handler : Read Scan Results
  1883.  */
  1884. static int airo_get_scan(struct net_device *dev,
  1885.  struct iw_request_info *info,
  1886.  struct iw_point *dwrq,
  1887.  char *extra)
  1888. {
  1889. struct airo_info *ai = dev->priv;
  1890. BSSListRid BSSList;
  1891. int rc;
  1892. char *current_ev = extra;
  1893. /* When we are associated again, the scan has surely finished.
  1894.  * Just in case, let's make sure enough time has elapsed since
  1895.  * we started the scan. - Javier */
  1896. if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) {
  1897. /* Important note : we don't want to block the caller
  1898.  * until results are ready for various reasons.
  1899.  * First, managing wait queues is complex and racy
  1900.  * (there may be multiple simultaneous callers).
  1901.  * Second, we grab some rtnetlink lock before comming
  1902.  * here (in dev_ioctl()).
  1903.  * Third, the caller can wait on the Wireless Event
  1904.  * - Jean II */
  1905. return -EAGAIN;
  1906. }
  1907. ai->scan_timestamp = 0;
  1908. /* There's only a race with proc_BSSList_open(), but its
  1909.  * consequences are begnign. So I don't bother fixing it - Javier */
  1910. /* Try to read the first entry of the scan result */
  1911. rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList));
  1912. if((rc) || (BSSList.index == 0xffff)) {
  1913. /* Client error, no scan results...
  1914.  * The caller need to restart the scan. */
  1915. return -ENODATA;
  1916. }
  1917. /* Read and parse all entries */
  1918. while((!rc) && (BSSList.index != 0xffff)) {
  1919. /* Translate to WE format this entry */
  1920. current_ev = airo_translate_scan(dev, current_ev,
  1921.  extra + IW_SCAN_MAX_DATA,
  1922.  &BSSList);
  1923. /* Read next entry */
  1924. rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
  1925.     &BSSList, sizeof(BSSList));
  1926. }
  1927. /* Length of data */
  1928. dwrq->length = (current_ev - extra);
  1929. dwrq->flags = 0; /* todo */
  1930. return 0;
  1931. }
  1932. #endif /* WIRELESS_EXT > 13 */
  1933. #ifdef WIRELESS_SPY
  1934. /*------------------------------------------------------------------*/
  1935. /*
  1936.  * Wireless Handler : set Spy List
  1937.  */
  1938. static int airo_set_spy(struct net_device *dev,
  1939. struct iw_request_info *info,
  1940. struct iw_point *dwrq,
  1941. char *extra)
  1942. {
  1943. struct airo_info *local = dev->priv;
  1944. struct sockaddr *address = (struct sockaddr *) extra;
  1945. /* Disable spy while we copy the addresses.
  1946.  * As we don't disable interrupts, we need to do this to avoid races */
  1947. local->spy_number = 0;
  1948. if (dwrq->length > 0) {
  1949. int i;
  1950. /* Copy addresses */
  1951. for (i = 0; i < dwrq->length; i++)
  1952. memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
  1953. /* Reset stats */
  1954. memset(local->spy_stat, 0, sizeof(struct iw_quality) * IW_MAX_SPY);
  1955. }
  1956. /* Enable addresses */
  1957. local->spy_number = dwrq->length;
  1958. return 0;
  1959. }
  1960. /*------------------------------------------------------------------*/
  1961. /*
  1962.  * Wireless Handler : get Spy List
  1963.  */
  1964. static int airo_get_spy(struct net_device *dev,
  1965. struct iw_request_info *info,
  1966. struct iw_point *dwrq,
  1967. char *extra)
  1968. {
  1969. struct airo_info *local = dev->priv;
  1970. struct sockaddr *address = (struct sockaddr *) extra;
  1971. int i;
  1972. dwrq->length = local->spy_number;
  1973. /* Copy addresses. */
  1974. for(i = 0; i < local->spy_number; i++)  {
  1975. memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
  1976. address[i].sa_family = AF_UNIX;
  1977. }
  1978. /* Copy stats to the user buffer (just after). */
  1979. if(local->spy_number > 0)
  1980. memcpy(extra  + (sizeof(struct sockaddr) * local->spy_number),
  1981.        local->spy_stat, sizeof(struct iw_quality) * local->spy_number);
  1982. /* Reset updated flags. */
  1983. for (i=0; i<local->spy_number; i++)
  1984. local->spy_stat[i].updated = 0;
  1985. return 0;
  1986. }
  1987. #endif /* WIRELESS_SPY */
  1988. /*------------------------------------------------------------------*/
  1989. /*
  1990.  * Commit handler : called after a bunch of SET operations
  1991.  */
  1992. static int airo_config_commit(struct net_device *dev,
  1993.       struct iw_request_info *info, /* NULL */
  1994.       void *zwrq, /* NULL */
  1995.       char *extra) /* NULL */
  1996. {
  1997. struct airo_info *local = dev->priv;
  1998. Resp rsp;
  1999. if (!local->need_commit)
  2000. return 0;
  2001. /* Some of the "SET" function may have modified some of the
  2002.  * parameters. It's now time to commit them in the card */
  2003. disable_MAC(local);
  2004. writeConfigRid(local);
  2005. enable_MAC(local, &rsp);
  2006. return 0;
  2007. }
  2008. /*------------------------------------------------------------------*/
  2009. /*
  2010.  * Structures to export the Wireless Handlers
  2011.  */
  2012. static const struct iw_priv_args airo_private_args[] = {
  2013. /*{ cmd,         set_args,                            get_args, name } */
  2014.   { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
  2015.     IW_PRIV_TYPE_BYTE | 2047, "airoioctl" },
  2016.   { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
  2017.     IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" },
  2018. };
  2019. #if WIRELESS_EXT > 12
  2020. static const iw_handler airo_handler[] =
  2021. {
  2022. (iw_handler) airo_config_commit, /* SIOCSIWCOMMIT */
  2023. (iw_handler) airo_get_name, /* SIOCGIWNAME */
  2024. (iw_handler) NULL, /* SIOCSIWNWID */
  2025. (iw_handler) NULL, /* SIOCGIWNWID */
  2026. (iw_handler) airo_set_freq, /* SIOCSIWFREQ */
  2027. (iw_handler) airo_get_freq, /* SIOCGIWFREQ */
  2028. (iw_handler) airo_set_mode, /* SIOCSIWMODE */
  2029. (iw_handler) airo_get_mode, /* SIOCGIWMODE */
  2030. (iw_handler) airo_set_sens, /* SIOCSIWSENS */
  2031. (iw_handler) airo_get_sens, /* SIOCGIWSENS */
  2032. (iw_handler) NULL, /* SIOCSIWRANGE */
  2033. (iw_handler) airo_get_range, /* SIOCGIWRANGE */
  2034. (iw_handler) NULL, /* SIOCSIWPRIV */
  2035. (iw_handler) NULL, /* SIOCGIWPRIV */
  2036. (iw_handler) NULL, /* SIOCSIWSTATS */
  2037. (iw_handler) NULL, /* SIOCGIWSTATS */
  2038. #ifdef WIRELESS_SPY
  2039. (iw_handler) airo_set_spy, /* SIOCSIWSPY */
  2040. (iw_handler) airo_get_spy, /* SIOCGIWSPY */
  2041. #else /* WIRELESS_SPY */
  2042. (iw_handler) NULL, /* SIOCSIWSPY */
  2043. (iw_handler) NULL, /* SIOCGIWSPY */
  2044. #endif /* WIRELESS_SPY */
  2045. (iw_handler) NULL, /* -- hole -- */
  2046. (iw_handler) NULL, /* -- hole -- */
  2047. (iw_handler) airo_set_wap, /* SIOCSIWAP */
  2048. (iw_handler) airo_get_wap, /* SIOCGIWAP */
  2049. (iw_handler) NULL, /* -- hole -- */
  2050. (iw_handler) airo_get_aplist, /* SIOCGIWAPLIST */
  2051. #if WIRELESS_EXT > 13
  2052. (iw_handler) airo_set_scan, /* SIOCSIWSCAN */
  2053. (iw_handler) airo_get_scan, /* SIOCGIWSCAN */
  2054. #else /* WIRELESS_EXT > 13 */
  2055. (iw_handler) NULL, /* SIOCSIWSCAN */
  2056. (iw_handler) NULL, /* SIOCGIWSCAN */
  2057. #endif /* WIRELESS_EXT > 13 */
  2058. (iw_handler) airo_set_essid, /* SIOCSIWESSID */
  2059. (iw_handler) airo_get_essid, /* SIOCGIWESSID */
  2060. (iw_handler) airo_set_nick, /* SIOCSIWNICKN */
  2061. (iw_handler) airo_get_nick, /* SIOCGIWNICKN */
  2062. (iw_handler) NULL, /* -- hole -- */
  2063. (iw_handler) NULL, /* -- hole -- */
  2064. (iw_handler) airo_set_rate, /* SIOCSIWRATE */
  2065. (iw_handler) airo_get_rate, /* SIOCGIWRATE */
  2066. (iw_handler) airo_set_rts, /* SIOCSIWRTS */
  2067. (iw_handler) airo_get_rts, /* SIOCGIWRTS */
  2068. (iw_handler) airo_set_frag, /* SIOCSIWFRAG */
  2069. (iw_handler) airo_get_frag, /* SIOCGIWFRAG */
  2070. (iw_handler) airo_set_txpow, /* SIOCSIWTXPOW */
  2071. (iw_handler) airo_get_txpow, /* SIOCGIWTXPOW */
  2072. (iw_handler) airo_set_retry, /* SIOCSIWRETRY */
  2073. (iw_handler) airo_get_retry, /* SIOCGIWRETRY */
  2074. (iw_handler) airo_set_encode, /* SIOCSIWENCODE */
  2075. (iw_handler) airo_get_encode, /* SIOCGIWENCODE */
  2076. (iw_handler) airo_set_power, /* SIOCSIWPOWER */
  2077. (iw_handler) airo_get_power, /* SIOCGIWPOWER */
  2078. };
  2079. /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
  2080.  * We want to force the use of the ioctl code, because those can't be
  2081.  * won't work the iw_handler code (because they simultaneously read
  2082.  * and write data and iw_handler can't do that).
  2083.  * Note that it's perfectly legal to read/write on a single ioctl command,
  2084.  * you just can't use iwpriv and need to force it via the ioctl handler.
  2085.  * Jean II */
  2086. static const iw_handler airo_private_handler[] =
  2087. {
  2088. NULL, /* SIOCIWFIRSTPRIV */
  2089. };
  2090. static const struct iw_handler_def airo_handler_def =
  2091. {
  2092. num_standard: sizeof(airo_handler)/sizeof(iw_handler),
  2093. num_private: sizeof(airo_private_handler)/sizeof(iw_handler),
  2094. num_private_args: sizeof(airo_private_args)/sizeof(struct iw_priv_args),
  2095. standard: (iw_handler *) airo_handler,
  2096. private: (iw_handler *) airo_private_handler,
  2097. private_args: (struct iw_priv_args *) airo_private_args,
  2098. };
  2099. #endif /* WIRELESS_EXT > 12 */
  2100. #endif /* WIRELESS_EXT */
  2101. /*
  2102.  * This defines the configuration part of the Wireless Extensions
  2103.  * Note : irq and spinlock protection will occur in the subroutines
  2104.  *
  2105.  * TODO :
  2106.  * o Check input value more carefully and fill correct values in range
  2107.  * o Test and shakeout the bugs (if any)
  2108.  *
  2109.  * Jean II
  2110.  *
  2111.  * Javier Achirica did a great job of merging code from the unnamed CISCO
  2112.  * developer that added support for flashing the card.
  2113.  */
  2114. static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  2115. {
  2116. int rc = 0;
  2117. #if defined(WIRELESS_EXT) && WIRELESS_EXT < 13
  2118. struct iwreq *wrq = (struct iwreq *) rq;
  2119. #endif /* WIRELESS_EXT < 13 */
  2120. switch (cmd) {
  2121. /* WE 13 and higher will use airo_handler_def */
  2122. #if defined(WIRELESS_EXT) && WIRELESS_EXT < 13
  2123. case SIOCGIWNAME: // Get name
  2124. airo_get_name(dev, NULL, (char *) &(wrq->u.name), NULL);
  2125. break;
  2126. case SIOCSIWFREQ: // Set frequency/channel
  2127. rc = airo_set_freq(dev, NULL, &(wrq->u.freq), NULL);
  2128. break;
  2129. case SIOCGIWFREQ: // Get frequency/channel
  2130. rc = airo_get_freq(dev, NULL, &(wrq->u.freq), NULL);
  2131. break;
  2132. case SIOCSIWESSID: // Set desired network name (ESSID)
  2133. {
  2134. char essidbuf[IW_ESSID_MAX_SIZE+1];
  2135. if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
  2136. rc = -E2BIG;
  2137. break;
  2138. }
  2139. if (copy_from_user(essidbuf, wrq->u.essid.pointer,
  2140.    wrq->u.essid.length)) {
  2141. rc = -EFAULT;
  2142. break;
  2143. }
  2144. rc = airo_set_essid(dev, NULL,
  2145.     &(wrq->u.essid), essidbuf);
  2146. }
  2147. break;
  2148. case SIOCGIWESSID: // Get current network name (ESSID)
  2149. {
  2150. char essidbuf[IW_ESSID_MAX_SIZE+1];
  2151. if (wrq->u.essid.pointer)
  2152. rc = airo_get_essid(dev, NULL,
  2153.     &(wrq->u.essid), essidbuf);
  2154. if ( copy_to_user(wrq->u.essid.pointer,
  2155.   essidbuf,
  2156.   wrq->u.essid.length) )
  2157. rc = -EFAULT;
  2158. }
  2159. break;
  2160. case SIOCSIWAP:
  2161. rc = airo_set_wap(dev, NULL, &(wrq->u.ap_addr), NULL);
  2162. break;
  2163. case SIOCGIWAP: // Get current Access Point (BSSID)
  2164. rc = airo_get_wap(dev, NULL, &(wrq->u.ap_addr), NULL);
  2165. break;
  2166. case SIOCSIWNICKN: // Set desired station name
  2167. {
  2168. char nickbuf[IW_ESSID_MAX_SIZE+1];
  2169. if (wrq->u.data.length > IW_ESSID_MAX_SIZE) {
  2170. rc = -E2BIG;
  2171. break;
  2172. }
  2173. if (copy_from_user(nickbuf, wrq->u.data.pointer,
  2174.    wrq->u.data.length)) {
  2175. rc = -EFAULT;
  2176. break;
  2177. }
  2178. rc = airo_set_nick(dev, NULL,
  2179.    &(wrq->u.data), nickbuf);
  2180. }
  2181. break;
  2182. case SIOCGIWNICKN: // Get current station name
  2183. {
  2184. char nickbuf[IW_ESSID_MAX_SIZE+1];
  2185. if (wrq->u.data.pointer)
  2186. rc = airo_get_nick(dev, NULL,
  2187.    &(wrq->u.data), nickbuf);
  2188. if ( copy_to_user(wrq->u.data.pointer,
  2189.   nickbuf,
  2190.   wrq->u.data.length) )
  2191. rc = -EFAULT;
  2192. }
  2193. break;
  2194. case SIOCSIWRATE: // Set the desired bit-rate
  2195. rc = airo_set_rate(dev, NULL, &(wrq->u.bitrate), NULL);
  2196. break;
  2197. case SIOCGIWRATE: // Get the current bit-rate
  2198. rc = airo_get_rate(dev, NULL, &(wrq->u.bitrate), NULL);
  2199. break;
  2200. case SIOCSIWRTS: // Set the desired RTS threshold
  2201. rc = airo_set_rts(dev, NULL, &(wrq->u.rts), NULL);
  2202. break;
  2203. case SIOCGIWRTS: // Get the current RTS threshold
  2204. rc = airo_get_rts(dev, NULL, &(wrq->u.rts), NULL);
  2205. break;
  2206. case SIOCSIWFRAG: // Set the desired fragmentation threshold
  2207. rc = airo_set_frag(dev, NULL, &(wrq->u.frag), NULL);
  2208. break;
  2209. case SIOCGIWFRAG: // Get the current fragmentation threshold
  2210. rc = airo_get_frag(dev, NULL, &(wrq->u.frag), NULL);
  2211. break;
  2212. case SIOCSIWMODE: // Set mode of operation
  2213. rc = airo_set_mode(dev, NULL, &(wrq->u.mode), NULL);
  2214. break;
  2215. case SIOCGIWMODE: // Get mode of operation
  2216. rc = airo_get_mode(dev, NULL, &(wrq->u.mode), NULL);
  2217. break;
  2218. case SIOCSIWENCODE: // Set WEP keys and mode
  2219. {
  2220. char keybuf[MAX_KEY_SIZE];
  2221. if (wrq->u.encoding.pointer) {
  2222. /* We actually have a key to set */
  2223. if (wrq->u.encoding.length > MAX_KEY_SIZE) {
  2224. rc = -E2BIG;
  2225. break;
  2226. }
  2227. if (copy_from_user(keybuf,
  2228.    wrq->u.encoding.pointer,
  2229.    wrq->u.encoding.length)) {
  2230. rc = -EFAULT;
  2231. break;
  2232. }
  2233. } else if (wrq->u.encoding.length != 0) {
  2234. rc = -EINVAL;
  2235. break;
  2236. }
  2237. rc = airo_set_encode(dev, NULL,
  2238.      &(wrq->u.encoding), keybuf);
  2239. }
  2240. break;
  2241. case SIOCGIWENCODE: // Get the WEP keys and mode
  2242. // Only super-user can see WEP key
  2243. // Note : this is needed only for very old versions of WE
  2244. if (!capable(CAP_NET_ADMIN)) {
  2245. rc = -EPERM;
  2246. break;
  2247. }
  2248. {
  2249. char keybuf[MAX_KEY_SIZE];
  2250. rc = airo_get_encode(dev, NULL,
  2251.      &(wrq->u.encoding), keybuf);
  2252. if (wrq->u.encoding.pointer) {
  2253. if (copy_to_user(wrq->u.encoding.pointer,
  2254.  keybuf,
  2255.  wrq->u.encoding.length))
  2256. rc = -EFAULT;
  2257. }
  2258. }
  2259. break;
  2260. case SIOCGIWTXPOW: // Get the current Tx-Power
  2261. rc=airo_get_txpow(dev, NULL, &(wrq->u.txpower), NULL);
  2262. break;
  2263. case SIOCSIWTXPOW:
  2264. rc=airo_set_txpow(dev, NULL, &(wrq->u.txpower), NULL);
  2265. break;
  2266. case SIOCSIWRETRY:
  2267. rc=airo_set_retry(dev, NULL, &(wrq->u.retry), NULL);
  2268. break;
  2269. case SIOCGIWRETRY:
  2270. rc=airo_get_retry(dev, NULL, &(wrq->u.retry), NULL);
  2271. break;
  2272. case SIOCGIWRANGE: // Get range of parameters
  2273. {
  2274. struct iw_range range;
  2275. rc = airo_get_range(dev, NULL,
  2276.     &(wrq->u.data), (char *) &range);
  2277. if (copy_to_user(wrq->u.data.pointer, &range,
  2278.  sizeof(struct iw_range)))
  2279. rc = -EFAULT;
  2280. }
  2281. break;
  2282. case SIOCGIWPOWER:
  2283. rc=airo_get_power(dev, NULL, &(wrq->u.power), NULL);
  2284. break;
  2285. case SIOCSIWPOWER:
  2286. rc=airo_set_power(dev, NULL, &(wrq->u.power), NULL);
  2287. break;
  2288. case SIOCGIWSENS:
  2289. rc = airo_get_sens(dev, NULL, &(wrq->u.sens), NULL);
  2290. break;
  2291. case SIOCSIWSENS:
  2292. rc = airo_set_sens(dev, NULL, &(wrq->u.sens), NULL);
  2293. break;
  2294. case SIOCGIWAPLIST:
  2295. {
  2296. char buffer[IW_MAX_AP * (sizeof(struct sockaddr) +
  2297.   sizeof(struct iw_quality))];
  2298. if (wrq->u.data.pointer) {
  2299. rc = airo_get_aplist(dev, NULL,
  2300.      &(wrq->u.data), buffer);
  2301. if (copy_to_user(wrq->u.data.pointer,
  2302.  buffer,
  2303.  (wrq->u.data.length *
  2304.   (sizeof(struct sockaddr) +
  2305.    sizeof(struct iw_quality)))
  2306.  ))
  2307. rc = -EFAULT;
  2308. }
  2309. }
  2310. break;
  2311. #ifdef WIRELESS_SPY
  2312. case SIOCSIWSPY: // Set the spy list
  2313. {
  2314. struct sockaddr address[IW_MAX_SPY];
  2315. /* Check the number of addresses */
  2316. if (wrq->u.data.length > IW_MAX_SPY) {
  2317. rc = -E2BIG;
  2318. break;
  2319. }
  2320. /* Get the data in the driver */
  2321. if (wrq->u.data.pointer) {
  2322. if (copy_from_user((char *) address,
  2323.    wrq->u.data.pointer,
  2324.    sizeof(struct sockaddr) *
  2325.    wrq->u.data.length)) {
  2326. rc = -EFAULT;
  2327. break;
  2328. }
  2329. } else if (wrq->u.data.length != 0) {
  2330. rc = -EINVAL;
  2331. break;
  2332. }
  2333. rc=airo_set_spy(dev, NULL, &(wrq->u.data),
  2334. (char *) address);
  2335. }
  2336. break;
  2337. case SIOCGIWSPY: // Get the spy list
  2338. {
  2339. char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
  2340.   sizeof(struct iw_quality))];
  2341. if (wrq->u.data.pointer) {
  2342. rc = airo_get_spy(dev, NULL,
  2343.   &(wrq->u.data), buffer);
  2344. if (copy_to_user(wrq->u.data.pointer,
  2345.  buffer,
  2346.  (wrq->u.data.length *
  2347.   (sizeof(struct sockaddr) +
  2348.    sizeof(struct iw_quality)))
  2349.  ))
  2350. rc = -EFAULT;
  2351. }
  2352. }
  2353. break;
  2354. #endif /* WIRELESS_SPY */
  2355. #ifdef CISCO_EXT
  2356. case SIOCGIWPRIV:
  2357. if(wrq->u.data.pointer) {
  2358. /* Set the number of ioctl available */
  2359. wrq->u.data.length = sizeof(airo_private_args) / sizeof( airo_private_args[0]);
  2360. /* Copy structure to the user buffer */
  2361. if(copy_to_user(wrq->u.data.pointer,
  2362. (u_char *) airo_private_args,
  2363. sizeof(airo_private_args)))
  2364. rc = -EFAULT;
  2365. }
  2366. break;
  2367. #endif /* CISCO_EXT */
  2368. #endif /* WIRELESS_EXT < 13 */
  2369. #ifdef CISCO_EXT
  2370. case AIROIDIFC:
  2371. #ifdef AIROOLDIDIFC
  2372. case AIROOLDIDIFC:
  2373. #endif
  2374. {
  2375. int val = AIROMAGIC;
  2376. aironet_ioctl com;
  2377. if (copy_from_user(&com,rq->ifr_data,sizeof(com)))
  2378. rc = -EFAULT;
  2379. else if (copy_to_user(com.data,(char *)&val,sizeof(val)))
  2380. rc = -EFAULT;
  2381. }
  2382. break;
  2383. case AIROIOCTL:
  2384. #ifdef AIROOLDIOCTL
  2385. case AIROOLDIOCTL:
  2386. #endif
  2387. /* Get the command struct and hand it off for evaluation by
  2388.  * the proper subfunction
  2389.  */
  2390. {
  2391. aironet_ioctl com;
  2392. if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
  2393. rc = -EFAULT;
  2394. break;
  2395. }
  2396. /* Seperate R/W functions bracket legality here
  2397.  */
  2398. if ( com.command <= AIROGMICSTATS )
  2399. rc = readrids(dev,&com);
  2400. else if ( com.command >= AIROPCAP && com.command <= AIROPLEAPUSR )
  2401. rc = writerids(dev,&com);
  2402. else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART )
  2403. rc = flashcard(dev,&com);
  2404. else
  2405. rc = -EINVAL;      /* Bad command in ioctl */
  2406. }
  2407. break;
  2408. #endif /* CISCO_EXT */
  2409. // All other calls are currently unsupported
  2410. default:
  2411. rc = -EOPNOTSUPP;
  2412. }
  2413. #if defined(WIRELESS_EXT) && WIRELESS_EXT < 13
  2414. /* WE 13 and higher will use airo_config_commit */
  2415. /* Some of the "SET" function may have modified some of the
  2416.  * parameters. It's now time to commit them in the card */
  2417. airo_config_commit(dev, NULL, NULL, NULL);
  2418. if (rc == -EINPROGRESS)
  2419. return 0;
  2420. #endif /* WIRELESS_EXT < 13 */
  2421. return rc;
  2422. }
  2423. #ifdef WIRELESS_EXT
  2424. /*
  2425.  * Get the Wireless stats out of the driver
  2426.  * Note : irq and spinlock protection will occur in the subroutines
  2427.  *
  2428.  * TODO :
  2429.  * o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
  2430.  * o Find the noise level
  2431.  *
  2432.  * Jean
  2433.  */
  2434. struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
  2435. {
  2436. struct airo_info *local = dev->priv;
  2437. StatusRid status_rid;
  2438. StatsRid stats_rid;
  2439. u32 *vals = stats_rid.vals;
  2440. /* Get stats out of the card */
  2441. readStatusRid(local, &status_rid);
  2442. readStatsRid(local, &stats_rid, RID_STATS);
  2443. /* The status */
  2444. local->wstats.status = status_rid.mode;
  2445. /* Signal quality and co. But where is the noise level ??? */
  2446. local->wstats.qual.qual = status_rid.signalQuality;
  2447. if (local->rssi)
  2448. local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
  2449. else
  2450. local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
  2451. local->wstats.qual.noise = 0;
  2452. local->wstats.qual.updated = 3;
  2453. /* Packets discarded in the wireless adapter due to wireless
  2454.  * specific problems */
  2455. local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */
  2456. local->wstats.discard.code = vals[6];/* RxWepErr */
  2457. local->wstats.discard.fragment = vals[30];
  2458. local->wstats.discard.retries = vals[10];
  2459. local->wstats.discard.misc = vals[1] + vals[32];
  2460. local->wstats.miss.beacon = vals[34];
  2461. return &local->wstats;
  2462. }
  2463. #endif /* WIRELESS_EXT */
  2464. #ifdef CISCO_EXT
  2465. /*
  2466.  * This just translates from driver IOCTL codes to the command codes to
  2467.  * feed to the radio's host interface. Things can be added/deleted
  2468.  * as needed.  This represents the READ side of control I/O to
  2469.  * the card
  2470.  */
  2471. static int readrids(struct net_device *dev, aironet_ioctl *comp) {
  2472. unsigned short ridcode;
  2473. unsigned char iobuf[2048];
  2474. struct airo_info *ai = dev->priv;
  2475. if (ai->flags & FLAG_FLASHING)
  2476. return -EIO;
  2477. switch(comp->command)
  2478. {
  2479. case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
  2480. case AIROGCFG: writeConfigRid (ai);
  2481.     ridcode = RID_CONFIG;       break;
  2482. case AIROGSLIST:    ridcode = RID_SSID;         break;
  2483. case AIROGVLIST:    ridcode = RID_APLIST;       break;
  2484. case AIROGDRVNAM:   ridcode = RID_DRVNAME;      break;
  2485. case AIROGEHTENC:   ridcode = RID_ETHERENCAP;   break;
  2486. case AIROGWEPKTMP:  ridcode = RID_WEP_TEMP;
  2487. /* Only super-user can read WEP keys */
  2488. if (!capable(CAP_NET_ADMIN))
  2489. return -EPERM;
  2490. break;
  2491. case AIROGWEPKNV:   ridcode = RID_WEP_PERM;
  2492. /* Only super-user can read WEP keys */
  2493. if (!capable(CAP_NET_ADMIN))
  2494. return -EPERM;
  2495. break;
  2496. case AIROGSTAT:     ridcode = RID_STATUS;       break;
  2497. case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
  2498. case AIROGSTATSC32: ridcode = RID_STATS;        break;
  2499. case AIROGMICSTATS:
  2500. if (copy_to_user(comp->data, &ai->micstats,
  2501.  min((int)comp->len,(int)sizeof(ai->micstats))))
  2502. return -EFAULT;
  2503. return 0;
  2504. default:
  2505. return -EINVAL;
  2506. break;
  2507. }
  2508. PC4500_readrid(ai,ridcode,iobuf,sizeof(iobuf));
  2509. /* get the count of bytes in the rid  docs say 1st 2 bytes is it.
  2510.  * then return it to the user
  2511.  * 9/22/2000 Honor user given length
  2512.  */
  2513. if (copy_to_user(comp->data, iobuf,
  2514.  min((int)comp->len, (int)sizeof(iobuf))))
  2515. return -EFAULT;
  2516. return 0;
  2517. }
  2518. /*
  2519.  * Danger Will Robinson write the rids here
  2520.  */
  2521. static int writerids(struct net_device *dev, aironet_ioctl *comp) {
  2522. struct airo_info *ai = dev->priv;
  2523. int  ridcode, enabled;
  2524. Resp      rsp;
  2525. static int (* writer)(struct airo_info *, u16 rid, const void *, int);
  2526. unsigned char iobuf[2048];
  2527. /* Only super-user can write RIDs */
  2528. if (!capable(CAP_NET_ADMIN))
  2529. return -EPERM;
  2530. if (ai->flags & FLAG_FLASHING)
  2531. return -EIO;
  2532. ridcode = 0;
  2533. writer = do_writerid;
  2534. switch(comp->command)
  2535. {
  2536. case AIROPSIDS:     ridcode = RID_SSID;         break;
  2537. case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
  2538. case AIROPAPLIST:   ridcode = RID_APLIST;       break;
  2539. case AIROPCFG: ai->config.len = 0;
  2540.     ridcode = RID_CONFIG;       break;
  2541. case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
  2542. case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
  2543. case AIROPLEAPPWD:  ridcode = RID_LEAPPASSWORD; break;
  2544. case AIROPWEPKEY:   ridcode = RID_WEP_TEMP; writer = PC4500_writerid;
  2545. break;
  2546. /* this is not really a rid but a command given to the card
  2547.  * same with MAC off
  2548.  */
  2549. case AIROPMACON:
  2550. if (enable_MAC(ai, &rsp) != 0)
  2551. return -EIO;
  2552. return 0;
  2553. /*
  2554.  * Evidently this code in the airo driver does not get a symbol
  2555.  * as disable_MAC. it's probably so short the compiler does not gen one.
  2556.  */
  2557. case AIROPMACOFF:
  2558. disable_MAC(ai);
  2559. return 0;
  2560. /* This command merely clears the counts does not actually store any data
  2561.  * only reads rid. But as it changes the cards state, I put it in the
  2562.  * writerid routines.
  2563.  */
  2564. case AIROPSTCLR:
  2565. PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,sizeof(iobuf));
  2566. enabled = ai->micstats.enabled;
  2567. memset(&ai->micstats,0,sizeof(ai->micstats));
  2568. ai->micstats.enabled = enabled;
  2569. if (copy_to_user(comp->data, iobuf,
  2570.  min((int)comp->len, (int)sizeof(iobuf))))
  2571. return -EFAULT;
  2572. return 0;
  2573. default:
  2574. return -EOPNOTSUPP; /* Blarg! */
  2575. }
  2576. if(comp->len > sizeof(iobuf))
  2577. return -EINVAL;
  2578. if (copy_from_user(iobuf,comp->data,comp->len))
  2579. return -EFAULT;
  2580. if (comp->command == AIROPCFG) {
  2581. ConfigRid *cfg = (ConfigRid *)iobuf;
  2582. if (ai->flags & FLAG_MIC_CAPABLE)
  2583. cfg->opmode |= MODE_MIC;
  2584. if ((cfg->opmode & 0xFF) == MODE_STA_IBSS)
  2585. ai->flags |= FLAG_ADHOC;
  2586. else
  2587. ai->flags &= ~FLAG_ADHOC;
  2588. }
  2589. if((*writer)(ai, ridcode, iobuf,comp->len))
  2590. return -EIO;
  2591. return 0;
  2592. }
  2593. /*****************************************************************************
  2594.  * Ancillary flash / mod functions much black magic lurkes here              *
  2595.  *****************************************************************************
  2596.  */
  2597. /*
  2598.  * Flash command switch table
  2599.  */
  2600. int flashcard(struct net_device *dev, aironet_ioctl *comp) {
  2601. int z;
  2602. int cmdreset(struct airo_info *);
  2603. int setflashmode(struct airo_info *);
  2604. int flashgchar(struct airo_info *,int,int);
  2605. int flashpchar(struct airo_info *,int,int);
  2606. int flashputbuf(struct airo_info *);
  2607. int flashrestart(struct airo_info *,struct net_device *);
  2608. /* Only super-user can modify flash */
  2609. if (!capable(CAP_NET_ADMIN))
  2610. return -EPERM;
  2611. switch(comp->command)
  2612. {
  2613. case AIROFLSHRST:
  2614. return cmdreset((struct airo_info *)dev->priv);
  2615. case AIROFLSHSTFL:
  2616. if (!((struct airo_info *)dev->priv)->flash &&
  2617. (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
  2618. return -ENOMEM;
  2619. return setflashmode((struct airo_info *)dev->priv);
  2620. case AIROFLSHGCHR: /* Get char from aux */
  2621. if(comp->len != sizeof(int))
  2622. return -EINVAL;
  2623. if (copy_from_user(&z,comp->data,comp->len))
  2624. return -EFAULT;
  2625. return flashgchar((struct airo_info *)dev->priv,z,8000);
  2626. case AIROFLSHPCHR: /* Send char to card. */
  2627. if(comp->len != sizeof(int))
  2628. return -EINVAL;
  2629. if (copy_from_user(&z,comp->data,comp->len))
  2630. return -EFAULT;
  2631. return flashpchar((struct airo_info *)dev->priv,z,8000);
  2632. case AIROFLPUTBUF: /* Send 32k to card */
  2633. if (!((struct airo_info *)dev->priv)->flash)
  2634. return -ENOMEM;
  2635. if(comp->len > FLASHSIZE)
  2636. return -EINVAL;
  2637. if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
  2638. return -EFAULT;
  2639. flashputbuf((struct airo_info *)dev->priv);
  2640. return 0;
  2641. case AIRORESTART:
  2642. if(flashrestart((struct airo_info *)dev->priv,dev))
  2643. return -EIO;
  2644. return 0;
  2645. }
  2646. return -EINVAL;
  2647. }
  2648. #define FLASH_COMMAND  0x7e7e
  2649. /*
  2650.  * STEP 1)
  2651.  * Disable MAC and do soft reset on
  2652.  * card.
  2653.  */
  2654. int cmdreset(struct airo_info *ai) {
  2655. disable_MAC(ai);
  2656. if(!waitbusy (ai)){
  2657. printk(KERN_INFO "Waitbusy hang before RESETn");
  2658. return -EBUSY;
  2659. }
  2660. OUT4500(ai,COMMAND,CMD_SOFTRESET);
  2661. set_current_state (TASK_UNINTERRUPTIBLE);
  2662. schedule_timeout (HZ);          /* WAS 600 12/7/00 */
  2663. if(!waitbusy (ai)){
  2664. printk(KERN_INFO "Waitbusy hang AFTER RESETn");
  2665. return -EBUSY;
  2666. }
  2667. return 0;
  2668. }
  2669. /* STEP 2)
  2670.  * Put the card in legendary flash
  2671.  * mode
  2672.  */
  2673. int setflashmode (struct airo_info *ai) {
  2674. ai->flags |= FLAG_FLASHING;
  2675. OUT4500(ai, SWS0, FLASH_COMMAND);
  2676. OUT4500(ai, SWS1, FLASH_COMMAND);
  2677. if (probe) {
  2678. OUT4500(ai, SWS0, FLASH_COMMAND);
  2679. OUT4500(ai, COMMAND,0x10);
  2680. } else {
  2681. OUT4500(ai, SWS2, FLASH_COMMAND);
  2682. OUT4500(ai, SWS3, FLASH_COMMAND);
  2683. OUT4500(ai, COMMAND,0);
  2684. }
  2685. set_current_state (TASK_UNINTERRUPTIBLE);
  2686. schedule_timeout (HZ/2); /* 500ms delay */
  2687. if(!waitbusy(ai)) {
  2688. ai->flags &= ~FLAG_FLASHING;
  2689. printk(KERN_INFO "Waitbusy hang after setflash moden");
  2690. return -EIO;
  2691. }
  2692. return 0;
  2693. }
  2694. /* Put character to SWS0 wait for dwelltime
  2695.  * x 50us for  echo .
  2696.  */
  2697. int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
  2698. int echo;
  2699. int waittime;
  2700. byte |= 0x8000;
  2701. if(dwelltime == 0 )
  2702. dwelltime = 200;
  2703. waittime=dwelltime;
  2704. /* Wait for busy bit d15 to go false indicating buffer empty */
  2705. while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) {
  2706. udelay (50);
  2707. waittime -= 50;
  2708. }
  2709. /* timeout for busy clear wait */
  2710. if(waittime <= 0 ){
  2711. printk(KERN_INFO "flash putchar busywait timeout! n");
  2712. return -EBUSY;
  2713. }
  2714. /* Port is clear now write byte and wait for it to echo back */
  2715. do {
  2716. OUT4500(ai,SWS0,byte);
  2717. udelay(50);
  2718. dwelltime -= 50;
  2719. echo = IN4500(ai,SWS1);
  2720. } while (dwelltime >= 0 && echo != byte);
  2721. OUT4500(ai,SWS1,0);
  2722. return (echo == byte) ? 0 : -EIO;
  2723. }
  2724. /*
  2725.  * Get a character from the card matching matchbyte
  2726.  * Step 3)
  2727.  */
  2728. int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
  2729. int           rchar;
  2730. unsigned char rbyte=0;
  2731. do {
  2732. rchar = IN4500(ai,SWS1);
  2733. if(dwelltime && !(0x8000 & rchar)){
  2734. dwelltime -= 10;
  2735. mdelay(10);
  2736. continue;
  2737. }
  2738. rbyte = 0xff & rchar;
  2739. if( (rbyte == matchbyte) && (0x8000 & rchar) ){
  2740. OUT4500(ai,SWS1,0);
  2741. return 0;
  2742. }
  2743. if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
  2744. break;
  2745. OUT4500(ai,SWS1,0);
  2746. }while(dwelltime > 0);
  2747. return -EIO;
  2748. }
  2749. /*
  2750.  * Transfer 32k of firmware data from user buffer to our buffer and
  2751.  * send to the card
  2752.  */
  2753. int flashputbuf(struct airo_info *ai){
  2754. int            nwords;
  2755. /* Write stuff */
  2756. OUT4500(ai,AUXPAGE,0x100);
  2757. OUT4500(ai,AUXOFF,0);
  2758. for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
  2759. OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
  2760. }
  2761. OUT4500(ai,SWS0,0x8000);
  2762. return 0;
  2763. }
  2764. /*
  2765.  *
  2766.  */
  2767. int flashrestart(struct airo_info *ai,struct net_device *dev){
  2768. int    i,status;
  2769. set_current_state (TASK_UNINTERRUPTIBLE);
  2770. schedule_timeout (HZ);          /* Added 12/7/00 */
  2771. ai->flags &= ~FLAG_FLASHING;
  2772. status = setup_card(ai, dev->dev_addr);
  2773. for( i = 0; i < MAX_FIDS; i++ ) {
  2774. ai->fids[i] = transmit_allocate( ai, 2312, i >= MAX_FIDS / 2 );
  2775. }
  2776. set_current_state (TASK_UNINTERRUPTIBLE);
  2777. schedule_timeout (HZ);          /* Added 12/7/00 */
  2778. return status;
  2779. }
  2780. #endif /* CISCO_EXT */
  2781. /*
  2782.     This program is free software; you can redistribute it and/or
  2783.     modify it under the terms of the GNU General Public License
  2784.     as published by the Free Software Foundation; either version 2
  2785.     of the License, or (at your option) any later version.
  2786.     This program is distributed in the hope that it will be useful,
  2787.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  2788.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2789.     GNU General Public License for more details.
  2790.     In addition:
  2791.     Redistribution and use in source and binary forms, with or without
  2792.     modification, are permitted provided that the following conditions
  2793.     are met:
  2794.     1. Redistributions of source code must retain the above copyright
  2795.        notice, this list of conditions and the following disclaimer.
  2796.     2. Redistributions in binary form must reproduce the above copyright
  2797.        notice, this list of conditions and the following disclaimer in the
  2798.        documentation and/or other materials provided with the distribution.
  2799.     3. The name of the author may not be used to endorse or promote
  2800.        products derived from this software without specific prior written
  2801.        permission.
  2802.     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  2803.     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  2804.     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  2805.     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  2806.     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  2807.     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  2808.     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2809.     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  2810.     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  2811.     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  2812.     POSSIBILITY OF SUCH DAMAGE.
  2813. */
  2814. module_init(airo_init_module);
  2815. module_exit(airo_cleanup_module);