Monday, October 10, 2011

atheros madwifi驱动分析

madwifi驱动阅读

该程序有好几个目录
ath: 物理网卡的控制函数,例如发送等
ath_rate: 速率控制的相关代码
hal: 硬件抽象层的相关库,不公开源代码
net80211: 802.11相关的代码,与物理层独立,完成诸如scanwapVAP等功能。

Ieee80211_wireless.c
static const iw_handler ieee80211_handlers[] = {
  (iw_handler) ieee80211_ioctl_siwrate,        /* SIOCSIWRATE */
  (iw_handler) ieee80211_ioctl_giwrate,        /* SIOCGIWRATE */

 模块的入口函数:if_ath_pci.c /module_init(init_ath_pci);
static int __init
init_ath_pci(void)
{
  printk(KERN_INFO “%s: %s\n”, dev_info, version);
  if (pci_register_driver(&ath_pci_drv_id) < 0) {
    printk(“ath_pci: No devices found, driver not installed.\n”);
    return (-ENODEV);
  }
#ifdef CONFIG_SYSCTL
  ath_sysctl_register();
#endif
  return (0);
}

module_init(init_ath_pci);

初始化会调用 ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)函数,进一步加载ath无线网卡:
  if (ath_attach(vdevice, dev) != 0)
    goto bad4;

If_ath.c (ath)文件实现ath_attach函数,该函数的实现非常复杂,关键的代码如下:
ath_attach(u_int16_t devid, struct net_device *dev)
{
  ……………
  ah = _ath_hal_attach(devid, sc, NULL, (void *) dev->mem_start, &status);
   
  可能是探测与硬件相关的东西,不能显示更进一步的代码:
  ………………..
  dev->hard_start_xmit = ath_hardstart;
  dev->do_ioctl = ath_ioctl;

ieee80211_ifattach(ic); 该函数在Ieee80211.c文件中实现
  ic->ic_vap_create = ath_vap_create;
  ic->ic_vap_delete = ath_vap_delete;

重点需要掌握ath与80211目录的关联,ath_vap_create是做什么的。
static struct ieee80211vap *
ath_vap_create(struct ieee80211com *ic, const char *name, int unit,
int opmode, int flags, struct net_device *mdev)
{
  ……………………
  ieee80211_vap_setup(ic, dev, name, unit, opmode, flags);
  ………….
(void) ieee80211_vap_attach(vap, ieee80211_media_change,  ieee80211_media_status);

Ieee80211_wireless.c
ieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev, const char *name, int unit, int opmode, int flags)->

调用下面的函数,实现ioctl函数,
ieee80211_ioctl_vattach(struct ieee80211vap *vap)
{
  struct net_device *dev = vap->iv_dev;
  dev->do_ioctl = ieee80211_ioctl;

这里就存在两次对dev->do_ioctl赋值的情况,一次是在ath_attach函数中,一次在
    ieee80211_ioctl_vattach函数中,怀疑第二次是不是就将第一次的覆盖了。
    ieee80211_ioctl函数就有很多的子函数用以实现不同的功能,以设置和获取速率为例:
    ieee80211_ioctl_siwrate(struct net_device *dev, struct iw_request_info  *info, struct iw_param *rrq, char *extra)

获取速率的ioctl函数的实现
ieee80211_ioctl_giwrate(struct net_device *dev,   struct iw_request_info  *info, struct iw_param *rrq, char *extra)
{
  struct ieee80211vap *vap = dev->priv;
  struct ifmediareq imr;
  int rate;
   
  memset(&imr, 0, sizeof(imr));
  vap->iv_media.ifm_status(vap->iv_dev, &imr);
  rrq->fixed = IFM_SUBTYPE(vap->iv_media.ifm_media) != IFM_AUTO;
  /* media status will have the current xmit rate if available */
  rate = ieee80211_media2rate(imr.ifm_active);  //这个函数的意思是将速率编号转换为实际的速率
  if (rate == -1)       /* IFM_AUTO */
    rate = 0;   //如果是auto,那么就返回0
  rrq->value = 1000000 * (rate / 2);
  return 0;
}

有关于速率的东西都在ifm_active变量中,这个变量包含了很多的属性,包括速率、模式等等,在if_media.h文件中
  #define    IFM_IEEE80211_DS1     5     /* Direct Sequence 1Mbps */
  #define    IFM_IEEE80211_DS2     6     /* Direct Sequence 2Mbps */
  #define    IFM_IEEE80211_DS5     7     /* Direct Sequence 5.5Mbps */
  #define    IFM_IEEE80211_DS11    8     /* Direct Sequence 11Mbps */

函数ieee80211com_media_status实现获得ifm_active变量
ieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr)
{
  struct ieee80211com *ic = dev->priv;   /*XXX*/
  imr->ifm_status = IFM_AVALID;
  if (!TAILQ_EMPTY(&ic->ic_vaps))
    imr->ifm_status |= IFM_ACTIVE;
  imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
}
通过上述分析,发现ifm_active变量的获得实际上是ieee80211com *ic结构体获得的。

数据发送过程分析:
static int
ath_hardstart(struct sk_buff *skb, struct net_device *dev)-> ath_tx_start(struct net_device *dev, struct ieee80211_node *ni, struct  ath_buf *bf, struct sk_buff *skb, int nextfraglen)
{
  ……….
  ath_rate_findrate(sc, an, shortPreamble, skb->len, &rix, &try0, &txrate);  //有关速率控制的东西
  ………
  ath_hal_setuptxdesc(ah, ds
                , pktlen          /* packet length */
                , hdrlen          /* header length */
                , atype           /* Atheros packet type */
                , MIN(ni->ni_txpower, 60)/* txpower */
                , txrate, try0    /* series 0 rate/tries */
                , keyix           /* key cache index */
                , antenna         /* antenna mode */
                , flags           /* flags */
                , ctsrate         /* rts/cts rate */
                , ctsduration     /* rts/cts duration */
                , icvlen          /* comp icv len */
                , ivlen           /* comp iv len */
                , comp       /* comp scheme */
  );  //与硬件相关的函数

  if (try0 != ATH_TXMAXTRY)
    ath_rate_setupxtxdesc(sc, an, ds, shortPreamble, skb->len, rix);  //速率控制的描述符
}

No comments:

Post a Comment