Main Page | Data Structures | Directories | File List | Data Fields | Globals

if_ath_ioctl.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 Massachusetts Institute of Technology
00003  * John Bicket
00004  */
00005 
00006 /*
00007  * Originally derived from the following.
00008  */
00009 
00010 /*
00011  * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions
00016  * are met:
00017  * 1. Redistributions of source code must retain the above copyright
00018  *    notice, this list of conditions and the following disclaimer,
00019  *    without modification.
00020  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
00021  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
00022  *    redistribution must be conditioned upon including a substantially
00023  *    similar Disclaimer requirement for further binary redistribution.
00024  * 3. Neither the names of the above-listed copyright holders nor the names
00025  *    of any contributors may be used to endorse or promote products derived
00026  *    from this software without specific prior written permission.
00027  *
00028  * Alternatively, this software may be distributed under the terms of the
00029  * GNU General Public License ("GPL") version 2 as published by the Free
00030  * Software Foundation.
00031  *
00032  * NO WARRANTY
00033  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00034  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00035  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
00036  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00037  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
00038  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00039  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00040  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00041  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00042  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00043  * THE POSSIBILITY OF SUCH DAMAGES.
00044  *
00045  * $Id: if_ath_ioctl.c,v 1.13 2005/01/10 06:40:06 jbicket Exp $
00046  */
00047 
00048 /*
00049  * Wireless extensions support for 802.11 common code.
00050  */
00051 #ifndef EXPORT_SYMTAB
00052 #define EXPORT_SYMTAB
00053 #endif
00054 
00055 #include <linux/config.h>
00056 #include <linux/version.h>
00057 #include <linux/module.h>
00058 #include <linux/init.h>
00059 #include <linux/netdevice.h>
00060 #include <linux/utsname.h>
00061 #include <linux/if_arp.h>               /* XXX for ARPHRD_ETHER */
00062 
00063 #if AH_BYTE_ORDER == AH_BIG_ENDIAN
00064 #define _OS_REG_WRITE(_ah, _reg, _val) do {                                 \
00065         if ( (_reg) >= 0x4000 && (_reg) < 0x5000)                           \
00066                 *((volatile u_int32_t *)((_ah)->ah_sh + (_reg))) =          \
00067                         __bswap32((_val));                                  \
00068         else                                                                \
00069                 *((volatile u_int32_t *)((_ah)->ah_sh + (_reg))) = (_val);  \
00070 } while (0)
00071 #define _OS_REG_READ(_ah, _reg) \
00072         (((_reg) >= 0x4000 && (_reg) < 0x5000) ? \
00073                 __bswap32(*((volatile u_int32_t *)((_ah)->ah_sh + (_reg)))) : \
00074                 *((volatile u_int32_t *)((_ah)->ah_sh + (_reg))))
00075 #else /* AH_LITTLE_ENDIAN */
00076 #define _OS_REG_WRITE(_ah, _reg, _val) do { \
00077         *((volatile u_int32_t *)((_ah)->ah_sh + (_reg))) = (_val); \
00078 } while (0)
00079 #define _OS_REG_READ(_ah, _reg) \
00080         *((volatile u_int32_t *)((_ah)->ah_sh + (_reg)))
00081 #endif /* AH_BYTE_ORDER */
00082 
00083 #if defined(AH_DEBUG) || defined(AH_REGOPS_FUNC) || defined(AH_DEBUG_ALQ)
00084 /* use functions to do register operations */
00085 #define OS_REG_WRITE(_ah, _reg, _val)   ath_hal_reg_write(_ah, _reg, _val)
00086 #define OS_REG_READ(_ah, _reg)          ath_hal_reg_read(_ah, _reg)
00087 
00088 extern  void __ahdecl ath_hal_reg_write(struct ath_hal *ah,
00089                 u_int reg, u_int32_t val);
00090 extern  u_int32_t __ahdecl ath_hal_reg_read(struct ath_hal *ah, u_int reg);
00091 #else
00092 /* inline register operations */
00093 #define OS_REG_WRITE(_ah, _reg, _val)   _OS_REG_WRITE(_ah, _reg, _val)
00094 #define OS_REG_READ(_ah, _reg)          _OS_REG_READ(_ah, _reg)
00095 #endif /* AH_DEBUG || AH_REGFUNC || AH_DEBUG_ALQ */
00096 
00097 #include <net/iw_handler.h>
00098 
00099 #include <asm/uaccess.h>
00100 
00101 #include "if_athvar.h"
00102 #ifdef CONFIG_NET_WIRELESS
00103 
00104 #define IS_UP(_dev) \
00105         (((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
00106 
00107 
00108 struct iw_statistics *
00109 ath_iw_getstats(struct net_device *dev)
00110 {
00111 #define NZ(x)   ((x) ? (x) : 1)
00112         struct ath_softc *sc = dev->priv;
00113 
00114         sc->ic_iwstats.status = 0;
00115         sc->ic_iwstats.discard.nwid = 0;
00116         sc->ic_iwstats.discard.code = 0;
00117         sc->ic_iwstats.discard.fragment = 0;
00118         sc->ic_iwstats.discard.retries = 0;
00119         sc->ic_iwstats.discard.misc = 0;
00120 
00121         sc->ic_iwstats.miss.beacon = 0;
00122 
00123         return &sc->ic_iwstats;
00124 #undef NZ
00125 }
00126 
00127 
00128 int
00129 ath_ioctl_giwname(struct net_device *dev,
00130                    struct iw_request_info *info,
00131                    char *name, char *extra)
00132 {
00133   struct ath_softc *sc = dev->priv;
00134   switch (sc->ic_curmode) {
00135   case IEEE80211_MODE_11A:
00136     strncpy(name, "IEEE 802.11a", IFNAMSIZ);
00137     break;
00138   case IEEE80211_MODE_11B:
00139     strncpy(name, "IEEE 802.11b", IFNAMSIZ);
00140     break;
00141   case IEEE80211_MODE_11G:
00142     strncpy(name, "IEEE 802.11g", IFNAMSIZ);
00143     break;
00144   case IEEE80211_MODE_TURBO:
00145     strncpy(name, "IEEE 802.11-TURBO", IFNAMSIZ);
00146     break;
00147   default:
00148     strncpy(name, "IEEE 802.11", IFNAMSIZ);
00149     break;
00150   }    
00151 
00152   return 0;
00153 }
00154 
00155 /*
00156  * Convert MHz frequency to IEEE channel number.
00157  */
00158 u_int
00159 mhz2ieee(u_int freq, u_int flags)
00160 {
00161         if (flags & IEEE80211_CHAN_2GHZ) {      /* 2GHz band */
00162                 if (freq == 2484)
00163                         return 14;
00164                 if (freq < 2484)
00165                         return (freq - 2407) / 5;
00166                 else
00167                         return 15 + ((freq - 2512) / 20);
00168         } else if (flags & IEEE80211_CHAN_5GHZ) {       /* 5Ghz band */
00169                 return (freq - 5000) / 5;
00170         } else {                                /* either, guess */
00171                 if (freq == 2484)
00172                         return 14;
00173                 if (freq < 2484)
00174                         return (freq - 2407) / 5;
00175                 if (freq < 5000)
00176                         return 15 + ((freq - 2512) / 20);
00177                 return (freq - 5000) / 5;
00178         }
00179 }
00180 
00181 
00182 int
00183 ath_ioctl_siwfreq(struct net_device *dev,
00184                         struct iw_request_info *info,
00185                         struct iw_freq *freq, char *extra)
00186 {
00187   struct ath_softc *sc = dev->priv;
00188   struct ieee80211channel *c;
00189   int i;
00190   
00191   if (freq->e > 1)
00192     return -EINVAL;
00193   if (freq->e == 1)
00194     i = mhz2ieee(freq->m / 100000, 0);
00195   else
00196     i = freq->m;
00197   if (i > IEEE80211_CHAN_MAX || isclr(sc->ic_chan_avail, i)) {
00198     printk ("channel not active %d\n", i);
00199     return -EINVAL;
00200   }
00201   c = &sc->ic_channels[i];
00202   if (c == sc->current_channel) /* no change, just return */
00203     return 0;
00204   sc->current_channel = c;
00205 
00206   return IS_UP(dev) ? -(dev->open)(dev) : 0;
00207 
00208 }
00209 int
00210 ath_ioctl_giwfreq(struct net_device *dev,
00211                                 struct iw_request_info *info,
00212                                 struct iw_freq *freq, char *extra)
00213 {
00214         struct ath_softc *sc = dev->priv;
00215 
00216         if (!sc || !sc->current_channel)
00217                 return -EINVAL;
00218 
00219         freq->m = sc->current_channel->ic_freq * 100000;
00220         freq->e = 1;
00221 
00222         return 0;
00223 }
00224 
00225 
00226 int
00227 ath_ioctl_giwessid(struct net_device *dev,
00228                                 struct iw_request_info *info,
00229                   struct iw_point *data, char *essid) {
00230   struct ath_softc *sc = dev->priv;
00231   
00232   data->flags = 1;              /* active */
00233   if (data->length > sc->ic_esslen) {
00234     data->length = sc->ic_esslen;
00235     memcpy(essid, sc->ic_essid, data->length);
00236   }
00237   
00238   return 0;
00239 
00240 }
00241 
00242 int
00243 ath_ioctl_siwessid(struct net_device *dev,
00244                                 struct iw_request_info *info,
00245                   struct iw_point *data, char *essid) {
00246 
00247   struct ath_softc *sc = dev->priv;
00248   
00249   if (data->flags == 0) {               /* ANY */
00250     memset(sc->ic_essid, 0, IEEE80211_NWID_LEN);
00251     sc->ic_esslen = 0;
00252   } else {
00253     int i, len;
00254     
00255     len = IW_ESSID_MAX_SIZE;
00256     if (len > IEEE80211_NWID_LEN)
00257       len = IEEE80211_NWID_LEN;
00258     memcpy(sc->ic_essid, essid, len);
00259     /* XXX: scan for \0 to calculate the length */
00260     for (i = 0; i < len && sc->ic_essid[i] != '\0'; i++)
00261       ;
00262     sc->ic_esslen = i;
00263   }
00264   return IS_UP(dev) ? -(dev->open)(dev) : 0;
00265   
00266 }
00267 
00268 
00269 int
00270 ath_ioctl_siwmode(struct net_device *dev,
00271                         struct iw_request_info *info,
00272                         __u32 *mode, char *extra)
00273 {
00274   struct ath_softc *sc = dev->priv;
00275 
00276   enum ieee80211_opmode newmode = IW_MODE_INFRA;
00277   switch (*mode) {
00278   case IW_MODE_INFRA:
00279     /* default ? */
00280     newmode = IEEE80211_M_STA;
00281     break;
00282   case IW_MODE_ADHOC:
00283     newmode = IEEE80211_M_IBSS;
00284     break;
00285   case IW_MODE_MASTER:
00286     newmode = IEEE80211_M_HOSTAP;
00287     break;
00288   }
00289   *mode = IW_MODE_ADHOC;
00290 
00291   if (newmode != sc->ic_opmode) {
00292     sc->ic_opmode = newmode;
00293     return IS_UP(dev) ? -(dev->open)(dev) : 0;
00294   }
00295 
00296 
00297   return 0;
00298 }
00299 
00300 int
00301 ath_ioctl_giwmode(struct net_device *dev,
00302                         struct iw_request_info *info,
00303                         __u32 *mode, char *extra)
00304 {
00305   struct ath_softc *sc = dev->priv;
00306 
00307   switch (sc->ic_opmode) {
00308   case IEEE80211_M_STA:
00309     *mode = IW_MODE_INFRA;
00310     break;
00311   case IEEE80211_M_IBSS:
00312     *mode = IW_MODE_ADHOC;
00313     break;
00314   case IEEE80211_M_HOSTAP:
00315     *mode = IW_MODE_MASTER;
00316     break;
00317   case IEEE80211_M_AHDEMO:
00318     /* does this exist ? */
00319     *mode = IW_MODE_ADHOC;
00320   case IEEE80211_M_MONITOR:
00321     /* XXX this is wrong */
00322     *mode = IW_MODE_ADHOC;
00323     break;
00324   }
00325   return 0;
00326 }
00327 
00328 
00329 int
00330 ath_ioctl_siwsens(struct net_device *dev,
00331                         struct iw_request_info *info,
00332                         struct iw_param *sens, char *extra)
00333 {
00334         return 0;
00335 }
00336 
00337 int
00338 ath_ioctl_giwsens(struct net_device *dev,
00339                         struct iw_request_info *info,
00340                         struct iw_param *sens, char *extra)
00341 {
00342         sens->value = 0;
00343         sens->fixed = 1;
00344 
00345         return 0;
00346 }
00347 
00348 int
00349 ath_ioctl_siwrate(struct net_device *dev,
00350                         struct iw_request_info *info,
00351                         struct iw_param *rrq, char *extra)
00352 {
00353   struct ath_softc *sc = dev->priv;
00354   int dot11Rate = 2 * (rrq->value / 1000000);
00355   int index = sc->sc_rixmap[dot11Rate & IEEE80211_RATE_VAL];
00356   
00357   const HAL_RATE_TABLE *rt = sc->sc_rates[sc->ic_curmode];
00358   KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
00359   if (index >= 0 && index < rt->rateCount && rt->info[index].valid) {
00360     sc->ic_fixed_rate = dot11Rate;
00361     return 0;
00362   }
00363 
00364   return -EINVAL;
00365 
00366 }
00367 
00368 int
00369 ath_ioctl_giwrate(struct net_device *dev,
00370                         struct iw_request_info *info,
00371                         struct iw_param *rrq, char *extra)
00372 {
00373   struct ath_softc *sc = dev->priv;
00374 
00375   int dot11Rate = sc->ic_fixed_rate;
00376   int index = sc->sc_rixmap[dot11Rate & IEEE80211_RATE_VAL];
00377   int rate = 0;
00378 
00379   const HAL_RATE_TABLE *rt = sc->sc_rates[sc->ic_curmode];
00380   KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
00381 
00382   if (index >= 0 && index < rt->rateCount && rt->info[index].valid) {
00383     rate = dot11Rate / 2;
00384   }
00385 
00386   rrq->value = 1000000 * rate;
00387 
00388   return 0;
00389 }
00390 
00391 int
00392 ath_ioctl_siwnickn(struct net_device *dev,
00393                          struct iw_request_info *info,
00394                          struct iw_point *data, char *nickname)
00395 {
00396         struct ath_softc *sc = dev->priv;
00397 
00398         if (data->length > IEEE80211_NWID_LEN)
00399                 return -EINVAL;
00400 
00401         memset(sc->ic_nickname, 0, IEEE80211_NWID_LEN);
00402         memcpy(sc->ic_nickname, nickname, data->length);
00403         sc->ic_nicknamelen = data->length;
00404 
00405         return 0;
00406 }
00407 
00408 int
00409 ath_ioctl_giwnickn(struct net_device *dev,
00410                          struct iw_request_info *info,
00411                          struct iw_point *data, char *nickname)
00412 {
00413         struct ath_softc *sc = dev->priv;
00414 
00415         if (data->length > sc->ic_nicknamelen + 1)
00416                 data->length = sc->ic_nicknamelen + 1;
00417         if (data->length > 0) {
00418                 memcpy(nickname, sc->ic_nickname, data->length-1);
00419                 nickname[data->length-1] = '\0';
00420         }
00421         return 0;
00422 }
00423 
00424 int
00425 ath_ioctl_siwrts(struct net_device *dev,
00426                        struct iw_request_info *info,
00427                        struct iw_param *rts, char *extra)
00428 {
00429   struct ath_softc *sc = dev->priv;
00430   u16 val;
00431   
00432   if (rts->disabled) {
00433     val = IEEE80211_RTS_MAX;
00434   } else if (IEEE80211_RTS_MIN > rts->value || rts->value > IEEE80211_RTS_MAX) {
00435     return -EINVAL;
00436   } else {
00437     val = rts->value;
00438   }
00439 
00440   if (val != sc->ic_rts_threshold) {
00441     sc->ic_rts_threshold = val;
00442   }
00443   return -EINVAL;
00444 }
00445 
00446 int
00447 ath_ioctl_giwrts(struct net_device *dev,
00448                        struct iw_request_info *info,
00449                        struct iw_param *rts, char *extra)
00450 {
00451   struct ath_softc *sc = dev->priv;
00452   rts->value = sc->ic_rts_threshold;
00453   rts->disabled = (rts->value == IEEE80211_RTS_MAX);
00454   rts->fixed = 1;
00455 
00456   return 0;
00457 }
00458 
00459 int
00460 ath_ioctl_siwfrag(struct net_device *dev,
00461                         struct iw_request_info *info,
00462                         struct iw_param *rts, char *extra)
00463 {
00464   return 0;
00465 }
00466 
00467 int
00468 ath_ioctl_giwfrag(struct net_device *dev,
00469                         struct iw_request_info *info,
00470                         struct iw_param *rts, char *extra)
00471 {
00472         rts->value = 2346;
00473         rts->disabled = (rts->value == 2346);
00474         rts->fixed = 1;
00475 
00476         return 0;
00477 }
00478 
00479 int
00480 ath_ioctl_siwap(struct net_device *dev,
00481                       struct iw_request_info *info,
00482                       struct sockaddr *ap_addr, char *extra)
00483 {
00484         struct ath_softc *sc = dev->priv;
00485 
00486         
00487         IEEE80211_ADDR_COPY(sc->bssid, &ap_addr->sa_data);
00488         /* looks like a zero address disables */
00489         return 0;
00490 }
00491 
00492 int
00493 ath_ioctl_giwap(struct net_device *dev,
00494                       struct iw_request_info *info,
00495                       struct sockaddr *ap_addr, char *extra)
00496 {
00497         struct ath_softc *sc = dev->priv;
00498 
00499         IEEE80211_ADDR_COPY(&ap_addr->sa_data, sc->bssid);
00500         ap_addr->sa_family = ARPHRD_ETHER;
00501         return 0;
00502 }
00503 
00504 int
00505 ath_ioctl_siwretry(struct net_device *dev,
00506                                  struct iw_request_info *info,
00507                                  struct iw_param *rrq, char *extra)
00508 {
00509   return 0;
00510 }
00511 
00512 int
00513 ath_ioctl_giwretry(struct net_device *dev,
00514                                  struct iw_request_info *info,
00515                                  struct iw_param *rrq, char *extra)
00516 {
00517 
00518   switch (rrq->flags & IW_RETRY_TYPE) {
00519   case IW_RETRY_LIFETIME:
00520     rrq->flags = IW_RETRY_LIFETIME;
00521     rrq->value = 1 * 1024;
00522     break;
00523   case IW_RETRY_LIMIT:
00524     rrq->flags = IW_RETRY_LIMIT;
00525     switch (rrq->flags & IW_RETRY_MODIFIER) {
00526     case IW_RETRY_MIN:
00527       rrq->flags |= IW_RETRY_MAX;
00528       rrq->value = 8;
00529       break;
00530     case IW_RETRY_MAX:
00531       rrq->flags |= IW_RETRY_MAX;
00532       rrq->value = 8;
00533       break;
00534     }
00535   }
00536   return 0;
00537 
00538 }
00539 
00540 int
00541 ath_ioctl_siwtxpow(struct net_device *dev,
00542                          struct iw_request_info *info,
00543                          struct iw_param *rrq, char *extra)
00544 {
00545   return 0;
00546 }
00547 
00548 int
00549 ath_ioctl_giwtxpow(struct net_device *dev,
00550                          struct iw_request_info *info,
00551                          struct iw_param *rrq, char *extra)
00552 {
00553 
00554         rrq->disabled = 1;
00555         rrq->fixed = 1;
00556         rrq->flags = IW_TXPOW_DBM;
00557         rrq->value = 0;
00558         return 0;
00559 }
00560 
00561 int
00562 ath_ioctl_siwpower(struct net_device *dev,
00563                          struct iw_request_info *info,
00564                          struct iw_param *wrq, char *extra)
00565 {
00566         return 0;
00567 }
00568 
00569 int
00570 ath_ioctl_giwpower(struct net_device *dev,
00571                         struct iw_request_info *info,
00572                         struct iw_param *rrq, char *extra)
00573 {
00574   rrq->disabled = 1;
00575   return 0;
00576 }
00577 
00578 static int
00579 ath_ioctl_setparam(struct net_device *dev, struct iw_request_info *info,
00580                          void *w, char *extra)
00581 {
00582   //struct ath_softc *sc = dev->priv;
00583   int *i = (int *) extra;
00584   int param = i[0];
00585   //int value = i[1];
00586   
00587   switch (param) {
00588     
00589   case IEEE80211_PARAM_MODE:
00590     /* fallthrough */
00591   default:
00592     return -EOPNOTSUPP;
00593   
00594   }
00595   return 0;
00596 }
00597 
00598 static int
00599 ath_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
00600                         void *w, char *extra)
00601 {
00602   struct ath_softc *sc = dev->priv;
00603   int *param = (int *) extra;
00604 
00605   switch (param[0]) {
00606   case IEEE80211_PARAM_MODE:
00607     param[0] = sc->ic_curmode;
00608    
00609   default:
00610     return -EOPNOTSUPP;
00611   }
00612   return 0;
00613 }
00614 
00615 int
00616 ath_ioctl_giwrange(struct net_device *dev,
00617                          struct iw_request_info *info,
00618                          struct iw_point *data, char *extra)
00619 {
00620         struct ath_softc *sc = dev->priv;
00621         struct iw_range *range = (struct iw_range *) extra;
00622         int i;
00623 
00624         data->length = sizeof(struct iw_range);
00625         memset(range, 0, sizeof(struct iw_range));
00626 
00627         /* TODO: could fill num_txpower and txpower array with
00628          * something; however, there are 128 different values.. */
00629 
00630         range->txpower_capa = IW_TXPOW_DBM;
00631 
00632         if (sc->ic_opmode == IEEE80211_M_STA ||
00633             sc->ic_opmode == IEEE80211_M_IBSS) {
00634                 range->min_pmp = 1 * 1024;
00635                 range->max_pmp = 65535 * 1024;
00636                 range->min_pmt = 1 * 1024;
00637                 range->max_pmt = 1000 * 1024;
00638                 range->pmp_flags = IW_POWER_PERIOD;
00639                 range->pmt_flags = IW_POWER_TIMEOUT;
00640                 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
00641                         IW_POWER_UNICAST_R | IW_POWER_ALL_R;
00642         }
00643 
00644         range->we_version_compiled = WIRELESS_EXT;
00645         range->we_version_source = 13;
00646 
00647         range->retry_capa = IW_RETRY_LIMIT;
00648         range->retry_flags = IW_RETRY_LIMIT;
00649         range->min_retry = 0;
00650         range->max_retry = 255;
00651 
00652         range->num_channels = IEEE80211_CHAN_MAX;       /* XXX */
00653 
00654         range->num_frequency = 0;
00655         for (i = 0; i <= IEEE80211_CHAN_MAX; i++)
00656           if (isset(sc->ic_chan_avail, i)) {
00657                         range->freq[range->num_frequency].i = i;
00658                         range->freq[range->num_frequency].m =
00659                                 sc->ic_channels[i].ic_freq * 100000;
00660                         range->freq[range->num_frequency].e = 1;
00661                         if (++range->num_frequency == IW_MAX_FREQUENCIES)
00662                                 break;
00663                 }
00664 
00665         /* Max quality is max field value minus noise floor */
00666         range->max_qual.qual  = 0xff - 161;
00667 
00668         /*
00669          * In order to use dBm measurements, 'level' must be lower
00670          * than any possible measurement (see iw_print_stats() in
00671          * wireless tools).  It's unclear how this is meant to be
00672          * done, but setting zero in these values forces dBm and
00673          * the actual numbers are not used.
00674          */
00675         range->max_qual.level = 0;
00676         range->max_qual.noise = 0;
00677 
00678         range->sensitivity = 3;
00679 
00680         range->max_encoding_tokens = IEEE80211_WEP_NKID;
00681         range->num_encoding_sizes = 2;
00682         range->encoding_size[0] = 5;
00683         range->encoding_size[1] = 13;
00684 
00685 
00686         /* estimated maximum TCP throughput values (bps) */
00687         range->throughput = 5500000;
00688 
00689         range->min_rts = 0;
00690         range->max_rts = 2347;
00691         range->min_frag = 256;
00692         range->max_frag = 2346;
00693 
00694         return 0;
00695 }
00696 
00697 static int ath_ioctl_getreg(struct net_device *dev,
00698                                      struct iw_request_info *info,
00699                                      void *wrqu, char *extra)
00700 {
00701   struct ath_softc *sc = dev->priv;
00702   uint32_t reg = *((uint32_t *) extra);
00703   uint32_t *res = (uint32_t *) extra;
00704 
00705   if (reg < 0x4000 || reg > 0x9000) {
00706     return -EINVAL;
00707   }
00708   *res = OS_REG_READ(sc->sc_ah, reg);
00709   return 0;
00710 }
00711 
00712 
00713 static int ath_ioctl_setreg(struct net_device *dev,
00714                              struct iw_request_info *info,
00715                              void *wrqu, char *extra) 
00716 {
00717   struct ath_softc *sc = dev->priv;
00718   int *i = (int *) extra;
00719   uint32_t reg = *i;
00720   uint32_t val = *(i + 1);
00721   
00722   if (reg < 0x4000 || reg > 0x9000) {
00723     return -EINVAL;
00724   }
00725 
00726   OS_REG_WRITE(sc->sc_ah, reg, val);
00727   return  0;
00728 }
00729 
00730 static int ath_ioctl_getrxhdr(struct net_device *dev,
00731                                      struct iw_request_info *info,
00732                                      void *wrqu, char *extra)
00733 {
00734   struct ath_softc *sc = dev->priv;
00735   uint32_t *res = (uint32_t *) extra;
00736 
00737   switch (sc->dev_type) {
00738   case ARPHRD_IEEE80211:   *res = 0; break;
00739   case ARPHRD_IEEE80211_PRISM:   *res = 1; break;
00740   default: 
00741     return -EINVAL;
00742   }
00743   return 0;
00744 }
00745 
00746 static int ath_ioctl_setrxhdr(struct net_device *dev,
00747                              struct iw_request_info *info,
00748                              void *wrqu, char *extra) 
00749 {
00750   struct ath_softc *sc = dev->priv;
00751   int param = *((int *)wrqu);
00752   uint32_t type = sc->dev_type;
00753 
00754   switch (param) {
00755   case 0: type = ARPHRD_IEEE80211;   break;
00756   case 1: type = ARPHRD_IEEE80211_PRISM;   break;
00757   default: 
00758     return -EINVAL;
00759   }
00760 
00761   if (type == sc->dev_type) {
00762     return 0;
00763   }
00764 
00765   sc->dev_type = type;
00766   return IS_UP(dev) ? -(dev->open)(dev) : 0;
00767 }
00768                            
00769 /* Structures to export the Wireless Handlers */
00770 static const iw_handler ath_handlers[] = {
00771         (iw_handler) NULL,                              /* SIOCSIWCOMMIT */
00772         (iw_handler) ath_ioctl_giwname,         /* SIOCGIWNAME */
00773         (iw_handler) NULL,                              /* SIOCSIWNWID */
00774         (iw_handler) NULL,                              /* SIOCGIWNWID */
00775         (iw_handler) ath_ioctl_siwfreq,         /* SIOCSIWFREQ */
00776         (iw_handler) ath_ioctl_giwfreq,         /* SIOCGIWFREQ */
00777         (iw_handler) ath_ioctl_siwmode,         /* SIOCSIWMODE */
00778         (iw_handler) ath_ioctl_giwmode,         /* SIOCGIWMODE */
00779         (iw_handler) ath_ioctl_siwsens,         /* SIOCSIWSENS */
00780         (iw_handler) ath_ioctl_giwsens,         /* SIOCGIWSENS */
00781         (iw_handler) NULL /* not used */,               /* SIOCSIWRANGE */
00782         (iw_handler) ath_ioctl_giwrange,                /* SIOCGIWRANGE */
00783         (iw_handler) NULL /* not used */,               /* SIOCSIWPRIV */
00784         (iw_handler) NULL /* kernel code */,            /* SIOCGIWPRIV */
00785         (iw_handler) NULL /* not used */,               /* SIOCSIWSTATS */
00786         (iw_handler) NULL /* kernel code */,            /* SIOCGIWSTATS */
00787         (iw_handler) NULL,                              /* SIOCSIWSPY */
00788         (iw_handler) NULL,                              /* SIOCGIWSPY */
00789         (iw_handler) NULL,                              /* -- hole -- */
00790         (iw_handler) NULL,                              /* -- hole -- */
00791         (iw_handler) ath_ioctl_siwap,           /* SIOCSIWAP */
00792         (iw_handler) ath_ioctl_giwap,           /* SIOCGIWAP */
00793         (iw_handler) NULL,                              /* -- hole -- */
00794         (iw_handler) NULL,                              /* SIOCGIWAPLIST */
00795         (iw_handler) NULL,                              /* SIOCSIWSCAN */
00796         (iw_handler) NULL,                              /* SIOCGIWSCAN */
00797         (iw_handler) ath_ioctl_siwessid,                /* SIOCSIWESSID */
00798         (iw_handler) ath_ioctl_giwessid,                /* SIOCGIWESSID */
00799         (iw_handler) ath_ioctl_siwnickn,                /* SIOCSIWNICKN */
00800         (iw_handler) ath_ioctl_giwnickn,                /* SIOCGIWNICKN */
00801         (iw_handler) NULL,                              /* -- hole -- */
00802         (iw_handler) NULL,                              /* -- hole -- */
00803         (iw_handler) ath_ioctl_siwrate,         /* SIOCSIWRATE */
00804         (iw_handler) ath_ioctl_giwrate,         /* SIOCGIWRATE */
00805         (iw_handler) ath_ioctl_siwrts,          /* SIOCSIWRTS */
00806         (iw_handler) ath_ioctl_giwrts,          /* SIOCGIWRTS */
00807         (iw_handler) ath_ioctl_siwfrag,         /* SIOCSIWFRAG */
00808         (iw_handler) ath_ioctl_giwfrag,         /* SIOCGIWFRAG */
00809         (iw_handler) ath_ioctl_siwtxpow,                /* SIOCSIWTXPOW */
00810         (iw_handler) ath_ioctl_giwtxpow,                /* SIOCGIWTXPOW */
00811         (iw_handler) ath_ioctl_siwretry,                /* SIOCSIWRETRY */
00812         (iw_handler) ath_ioctl_giwretry,                /* SIOCGIWRETRY */
00813         (iw_handler) NULL,              /* SIOCSIWENCODE */
00814         (iw_handler) NULL,              /* SIOCGIWENCODE */
00815         (iw_handler) ath_ioctl_siwpower,                /* SIOCSIWPOWER */
00816         (iw_handler) ath_ioctl_giwpower,                /* SIOCGIWPOWER */
00817 };
00818 
00819 static const iw_handler ath_priv_handlers[] = {
00820         (iw_handler) ath_ioctl_setparam,                /* SIOCWFIRSTPRIV+0 */
00821         (iw_handler) ath_ioctl_getparam,                /* SIOCWFIRSTPRIV+1 */
00822         (iw_handler) ath_ioctl_setreg, 
00823         (iw_handler) ath_ioctl_getreg, 
00824         (iw_handler) ath_ioctl_setrxhdr, 
00825         (iw_handler) ath_ioctl_getrxhdr, 
00826 };
00827 static const struct iw_priv_args ath_priv_args[] = {
00828         { IEEE80211_IOCTL_SETPARAM,
00829           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam" },
00830         { IEEE80211_IOCTL_SETREG,
00831           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setreg" },
00832         { IEEE80211_IOCTL_GETREG,
00833           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
00834           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getreg" },
00835         { IEEE80211_IOCTL_SETRXHDR,
00836           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrxhdr" },
00837         { IEEE80211_IOCTL_GETRXHDR,
00838           0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrxhdr" },
00839 #if WIRELESS_EXT >= 12
00840         /*
00841          * These depends on sub-ioctl support which added in version 12.
00842          */
00843         { IEEE80211_IOCTL_GETPARAM,
00844           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
00845           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" },
00846         /* sub-ioctl handlers */
00847         { IEEE80211_IOCTL_SETPARAM,
00848           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
00849         { IEEE80211_IOCTL_GETPARAM,
00850           0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
00851         /* sub-ioctl definitions */
00852         { IEEE80211_PARAM_TURBO,
00853           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "turbo" },
00854         { IEEE80211_PARAM_TURBO,
00855           0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_turbo" },
00856         { IEEE80211_PARAM_MODE,
00857           IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "mode" },
00858         { IEEE80211_PARAM_MODE,
00859           0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_mode" },
00860 #endif /* WIRELESS_EXT >= 12 */
00861 };
00862 
00863 const struct iw_handler_def ath_iw_handler_def = {
00864 #define N(a)    (sizeof (a) / sizeof (a[0]))
00865         .standard               = (iw_handler *) ath_handlers,
00866         .num_standard           = N(ath_handlers),
00867         .private                = (iw_handler *) ath_priv_handlers,
00868         .num_private            = N(ath_priv_handlers),
00869         .private_args           = (struct iw_priv_args *) ath_priv_args,
00870         .num_private_args       = N(ath_priv_args),
00871 #undef N
00872 };
00873 #endif /* CONFIG_NET_WIRELESS */

Generated on Mon Nov 21 15:58:10 2005 for openwifi by  doxygen 1.4.1