Monday, October 10, 2011

madwifi学习心得一

madwifi学习记录(1)
    1. madwifi的结构,主要是有三层,hal是硬件层,然后是ath层,在之上的是802.11层,整个madwifi源码中重要的就是hal文件夹(硬 件),ath文件夹,ath_rate文件夹(动态调整tx rate的三种算法,默认使用sample),net80211文件夹(802.11协议相关),tools文件夹(一些工具)
    2. madwifi中hal是硬件相关的函数信息等,在hal文件夹下提供了需要的头文件,在hal/public下有该版本madwifi可以适应的硬件体 系结构,比如用powerpc-be-elf.hal.o.uu,需要用uudecode这个工具来解码他,命令为uudecode powerpc-be-elf.hal.o.uu,如果出现了提示没有‘end’的错误,可能是文件格式问题,用dos2unix把该文件格式转换一下就 可以,然后如果出现编译器命令不对,则可能修改powerpc-be-elf.inc文件中的TOOLPREFIX,指向编译器
    3. madwifi启动的时候会先扫描硬件网卡,然后如果发现了设备就会注册该设备(ath),其注册的过程中,会检查改网卡的设备id,这个东西有两个:在 ath下的if_ath_pci.c下pci_device_id 结构中,有一个静态表,描述了PCI id,第一个0×168c,是指atheros厂商的标志vendor,第二个是网卡的device id,如果扫描到的硬件不在这个表里是无法加载的,其定义可以在hal下的ah_devid.h文件中找到
    4. madwifi加载到内核的过程需要先加载模块,有两种方式modprobe命令和insmod命令(看看开发板是不是支持第一个命令),用 modeprobe可以直接加载ath_pci.o然后会把相关的模块(根据依赖关系)加载进来,如果不支持该命令则需要用insmod自己手动根据依赖 关系来加载各个模块,需要加载的模块及其顺序为:

        insmod wlan.o
        insmod ath_hal.o
        insmod ath_rate_amrr.o
        insmod ath_rate_onoe.o
        insmod ath_rate_sample.o
        insmod wlan_acl.o
        insmod wlan_ccmp.o
        insmod wlan_scan_ap.o
        insmod wlan_scan_sta.o
        insmod wlan_tkip.o
        insmod wlan_wep.o
        insmod wlan_xauth.o
        insmod ath_pci.o

    5. 在识别了网卡后,ath_pci_probe会使内核先初始化该设备,然后检查内核是否支持本设备的DMA寻址位数,建立内存映射等,创建 ath_pci_softc结构实例,部分初始化ath_softc中的net_device dev,最后调用ath_attach()函数,该函数会将识别的网卡device id进行处理,比如对比version(就是一个表示时间的串),然后准备激活网卡



madwifi学习记录(2)
    1. madwifi发送数据的过程为:首先在初始化的时候ath_attach函数会设置发送数据函数dev->hard_start_xmit = ath_hardstart, 然后在ath_hardstart函数中会有这些设置:
    if ((dev->flags & IFF_RUNNING) == 0 || sc->sc_invalid) 检测硬件是否已经启用并且判断sc是否与hal层连接好
    STAILQ_INIT(&bf_head);初始化bf_head结构体
    skb->data是上层传过来的数据,可以(struct ether_header *) skb->data
    ATH_SUPERG_FF的那个define是关于G模式的一个“快速帧”功能,Atheros的某种技术
    skb = ieee80211_encap(ni, skb, &framecnt);为数据包封装802.11帧头
    framecnt表示分段的个数,如果是只有一个就单纯发送,如果是多个,要进行一些判断然后为每段分配一个硬件缓冲区,并且发送在进行了上述过程后调用ath_tx_start函数进行下一步的参数设置

    2 . 总体发送数据过程为:ath_hardstart 、 ath_tx_start 、 ath_tx_txqaddbuf(放入发送队列)、ath_hal_txstart(发送),ath_hal_txstart就是在hal中定义的了,只能找到相应的define

    3. madwifi接收数据是通过中断执行,madwifi的中断处理函数为:ath_intr(),用status & HAL_INT_RX表示为数据接收,然后做相应处理

    4. 总体接收数据过程为:ath_rx_tasklet 、 ieee80211_input 、 ieee80211_deliver_data 、netif_rx(skb)(linux内核提供的函数)



madwifi学习记录(3)

本次madwifi学习的记录主要跟txq相关,结构为struct ath_txq,做个第一次和第二次的连接,以及夭折了的softmac
    1. ath_txq结构里比较有用的几个字段:qnum是记录在哪个队列,即队列号,depth记录当前队列长度,totalqueued记录总共曾经有多少个包放入过队列,axq_q貌似就是ath_buf的一个链表,会存着真正的数据
    2. 基本上对于txq的操作是通过ATH_TXQ_XXXXX函数来实现了,除了LOCK和UNLOCK之外,比较有用的是 ATH_TXQ_INSERT_TAIL,和ATH_TXQ_REMOVE_HEAD,他们除了会更新txq那个链表,也会调整depth,链表的最根本 定义及使用方法在/madwifi/include/sys/queue.h下
    3. 在ath_tx_txqaddbuf中调用ath_hal_txstart后不会立即减少depth,depth的减少是在processq中ATH_TXQ_REMOVE_HEAD后导致的。
    4. 硬件发包具体的发送方式猜测是多个包同时发送出去,或者说是将一个txq->axq_qnum中的包发干净,之后再传送中断,才会有q0123的捕获。主要依据有:
        (a). 在ath_tx_txqaddbuf中调用ath_hal_txstart之前设置当txq->axq_depth大于10的时候再调用 ath_hal_txstart,否则直接退出该函数,结果没有进入processq的结果输出,只有又有新包调用ath_tx_txqaddbuf,换 句话讲没有再出现发送包之后的中断,只有txq->axq_depth的累加,猜测是积累的包没有发完又添加新包,结果该qnum的队列发不干净, 没有返回中断
        (b). 每次ath_tx_tasklet_q0123函数都会在接到中断后调用 ath_tx_processq,在ath_tx_processq中会将该qnum的txq不断的ATH_TXQ_REMOVE_HEAD,depth 不断的减,直到该txq为空,才会退出。

    5. 在if_athvar.h中定义了TAIL_DROP_COUNT, 默认值为50, 这个数值是在限定txq的长度,如果txq的depth长于这个限定会丢包, 不会发送,ath_hardstart中使用了它
    if (txq->axq_depth > TAIL_DROP_COUNT) {
        sc->sc_stats.ast_tx_discard++;
        goto hardstart_fail;
    }

    6. 在hal/ah.h中定义了qnum的类型,HAL_NUM_TX_QUEUES 为最大允许定义的队列的个数,typedef的HAL_TX_QUEUE定义了各个序号的qnum的职能
    typedef enum {
        HAL_TX_QUEUE_INACTIVE    = 0,        /* queue is inactive/unused */
        HAL_TX_QUEUE_DATA    = 1,        /* data xmit q’s */
        HAL_TX_QUEUE_BEACON    = 2,        /* beacon xmit q */
        HAL_TX_QUEUE_CAB    = 3,        /* “crap after beacon” xmit q */
        HAL_TX_QUEUE_UAPSD    = 4,        /* u-apsd power save xmit q */
    } HAL_TX_QUEUE;





No comments:

Post a Comment