📄 wavelan.c
字号:
case SIOCSIWNWID: /* Set NWID in WaveLAN. */ if(wrq->u.nwid.on) { /* Set NWID in psa. */ psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8; psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF; psa.psa_nwid_select = 0x01; psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, (unsigned char *)psa.psa_nwid, 3); /* Set NWID in mmc. */ m.w.mmw_netw_id_l = wrq->u.nwid.nwid & 0xFF; m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8; mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2); mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00); } else { /* Disable NWID in the psa. */ psa.psa_nwid_select = 0x00; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_nwid_select - (char *)&psa, (unsigned char *)&psa.psa_nwid_select, 1); /* Disable NWID in the mmc (no filtering). */ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID); }#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr);#endif break; case SIOCGIWNWID: /* Read the NWID. */ psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa, (unsigned char *)psa.psa_nwid, 3); wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; wrq->u.nwid.on = psa.psa_nwid_select; break; case SIOCSIWFREQ: /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) ret = wv_set_frequency(ioaddr, &(wrq->u.freq)); else ret = -EOPNOTSUPP; break; case SIOCGIWFREQ: /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). * Does it work for everybody, especially old cards? */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { unsigned short freq; /* Ask the EEPROM to read the frequency from the first area. */ fee_read(ioaddr, 0x00, &freq, 1); wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000; wrq->u.freq.e = 1; } else { int bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 }; psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa, (unsigned char *)&psa.psa_subband, 1); if(psa.psa_subband <= 4) { wrq->u.freq.m = bands[psa.psa_subband]; wrq->u.freq.e = (psa.psa_subband != 0); } else ret = -EOPNOTSUPP; } break; case SIOCSIWSENS: /* Set the level threshold. */ if(!suser()) return -EPERM; psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, (unsigned char *) &psa.psa_thr_pre_set, 1);#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr);#endif mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set); break; case SIOCGIWSENS: /* Read the level threshold. */ psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa, (unsigned char *) &psa.psa_thr_pre_set, 1); wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F; break; case SIOCSIWENCODE: /* Set encryption key. */ if(!mmc_encr(ioaddr)) { ret = -EOPNOTSUPP; break; } if(wrq->u.encoding.method) { /* Enable encryption. */ int i; long long key = wrq->u.encoding.code; for(i = 7; i >= 0; i--) { psa.psa_encryption_key[i] = key & 0xFF; key >>= 8; } psa.psa_encryption_select = 1; psa_write(ioaddr, lp->hacr, (char *) &psa.psa_encryption_select - (char *) &psa, (unsigned char *) &psa.psa_encryption_select, 8+1); mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); mmc_write(ioaddr, mmwoff(0, mmw_encr_key), (unsigned char *) &psa.psa_encryption_key, 8); } else { /* Disable encryption. */ psa.psa_encryption_select = 0; psa_write(ioaddr, lp->hacr, (char *) &psa.psa_encryption_select - (char *) &psa, (unsigned char *) &psa.psa_encryption_select, 1); mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); }#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr);#endif break; case SIOCGIWENCODE: /* Read the encryption key. */ if(!mmc_encr(ioaddr)) { ret = -EOPNOTSUPP; break; } /* Only super-user can see encryption key. */ if(!suser()) { ret = -EPERM; break; } else { int i; long long key = 0; psa_read(ioaddr, lp->hacr, (char *) &psa.psa_encryption_select - (char *) &psa, (unsigned char *) &psa.psa_encryption_select, 1+8); for(i = 0; i < 8; i++) { key <<= 8; key += psa.psa_encryption_key[i]; } wrq->u.encoding.code = key; /* encryption is enabled */ if(psa.psa_encryption_select) wrq->u.encoding.method = mmc_encr(ioaddr); else wrq->u.encoding.method = 0; } break; case SIOCGIWRANGE: /* basic checking */ if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_range range; /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(struct iw_range)); if(ret) break; /* Set the length (useless: it's constant). */ wrq->u.data.length = sizeof(struct iw_range); /* Set information in the range struct. */ range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */ range.min_nwid = 0x0000; range.max_nwid = 0xFFFF; /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { range.num_channels = 10; range.num_frequency = wv_frequency_list(ioaddr, range.freq, IW_MAX_FREQUENCIES); } else range.num_channels = range.num_frequency = 0; range.sensitivity = 0x3F; range.max_qual.qual = MMR_SGNL_QUAL; range.max_qual.level = MMR_SIGNAL_LVL; range.max_qual.noise = MMR_SILENCE_LVL; /* Copy structure to the user buffer. */ copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)); } break; case SIOCGIWPRIV: /* Basic checking */ if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_priv_args priv[] = { /* cmd, set_args, get_args, name */ { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" }, { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" }, { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" }, { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, }; /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(priv)); if(ret) break; /* Set the number of available ioctls. */ wrq->u.data.length = 4; /* Copy structure to the user buffer. */ copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)); } break;#ifdef WIRELESS_SPY case SIOCSIWSPY: /* Set the spy list */ /* Check the number of addresses. */ if(wrq->u.data.length > IW_MAX_SPY) { ret = -E2BIG; break; } lp->spy_number = wrq->u.data.length; /* Are there are addresses to copy? */ if(lp->spy_number > 0) { struct sockaddr address[IW_MAX_SPY]; int i; /* Verify where the user has set his addresses. */ ret = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number); if(ret) break; /* Copy addresses to the driver. */ copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number); /* Copy addresses to the lp structure. */ for(i = 0; i < lp->spy_number; i++) { memcpy(lp->spy_address[i], address[i].sa_data, WAVELAN_ADDR_SIZE); } /* Reset structure. */ memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);#ifdef DEBUG_IOCTL_INFO printk(KERN_DEBUG "SetSpy: set of new addresses is: \n"); for(i = 0; i < wrq->u.data.length; i++) printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n", lp->spy_address[i][0], lp->spy_address[i][1], lp->spy_address[i][2], lp->spy_address[i][3], lp->spy_address[i][4], lp->spy_address[i][5]);#endif /* DEBUG_IOCTL_INFO */ } break; case SIOCGIWSPY: /* Get the spy list and spy stats. */ /* Set the number of addresses */ wrq->u.data.length = lp->spy_number; /* Does the user want to have the addresses back? */ if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { struct sockaddr address[IW_MAX_SPY]; int i; /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, (sizeof(iw_qual) + sizeof(struct sockaddr)) * IW_MAX_SPY); if(ret) break; /* Copy addresses from the lp structure. */ for(i = 0; i < lp->spy_number; i++) { memcpy(address[i].sa_data, lp->spy_address[i], WAVELAN_ADDR_SIZE); address[i].sa_family = AF_UNIX; } /* Copy addresses to the user buffer. */ copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number); /* Copy stats to the user buffer (just after). */ copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr) * lp->spy_number), lp->spy_stat, sizeof(iw_qual) * lp->spy_number); /* Reset updated flags. */ for(i = 0; i < lp->spy_number; i++) lp->spy_stat[i].updated = 0x0; } /* if(pointer != NULL) */ break;#endif /* WIRELESS_SPY */ /* ------------------ PRIVATE IOCTL ------------------ */ case SIOCSIPQTHR: if(!suser()) return -EPERM; psa.psa_quality_thr = *(wrq->u.name) & 0x0F; psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, (unsigned char *)&psa.psa_quality_thr, 1);#ifdef SET_PSA_CRC /* update the Wavelan checksum */ update_psa_checksum(dev, ioaddr, lp->hacr);#endif mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr); break; case SIOCGIPQTHR: psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa, (unsigned char *)&psa.psa_quality_thr, 1); *(wrq->u.name) = psa.psa_quality_thr & 0x0F; break;#ifdef HISTOGRAM case SIOCSIPHISTO: /* Verify that the user is root. */ if(!suser()) return -EPERM; /* Check the number of intervals. */ if(wrq->u.data.length > 16) { ret = -E2BIG; break; } lp->his_number = wrq->u.data.length; /* Are there addresses to copy? */ if(lp->his_number > 0) { /* Verify where the user has set his addresses. */ ret = verify_area(VERIFY_READ, wrq->u.data.pointer, sizeof(char) * lp->his_number); if(ret) break; /* Copy interval ranges to the driver */ copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number); /* Reset structure. */ memset(lp->his_sum, 0x00, sizeof(long) * 16); } break; case SIOCGIPHISTO: /* Set the number of intervals. */ wrq->u.data.length = lp->his_number; /* Give back the distribution statistics */ if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) { /* Verify the user buffer. */ ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(long) * 16); if(ret) break; /* Copy data to the user buffer. */ copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number); } /* if(pointer != NULL) */ break;#endif /* HISTOGRAM */ /* ------------------- OTHER IOCTL ------------------- */ default: ret = -EOPNOTSUPP; } /* Enable interrupts and restore flags. */ wv_splx(x);#ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);#endif return ret;}/*------------------------------------------------------------------*//* * Get wireless statistics. * Called by /proc/net/wireless */static iw_stats *wavelan_get_wireless_stats(device * dev){ u_long ioaddr = dev->base_addr; net_local * lp = (net_local *) dev->priv; mmr_t m; iw_stats * wstats; unsigned long x;#ifdef DEBUG_IOCTL_TRACE printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);#endif /* Disable interrupts and save flags. */ x = wv_splhi(); if(lp == (net_local *) NULL) return (iw_stats *) NULL; wstats = &lp->wstats; /* Get data from the mmc. */ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2); mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4); mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); /* Copy data to wireless stuff. */ wstats->status = m.mmr_dce_status & MMR_DCE_STATUS; wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; wstats->qual.level = m.mmr_signal_lvl & MM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -