linux网卡驱动dm9000_poll_work函数分析

来源:互联网 发布:淘宝仓鼠笼子 编辑:程序博客网 时间:2024/06/15 07:23
static void
dm9000_poll_work(struct work_struct *w)
{
struct delayed_work *dw = container_of(w, struct delayed_work, work);//获得结构体struct delayed_work,详见注释一                                                                                                                       
board_info_t *db = container_of(dw, board_info_t, phy_poll);//获得结构体board_info_t的入口地址,这句话的意思同上                                                                                                                                  
struct net_device *ndev = db->ndev;

if (db->flags & DM9000_PLATF_SIMPLE_PHY &&
    !(db->flags & DM9000_PLATF_EXT_PHY)) {
unsigned nsr = dm9000_read_locked(db, DM9000_NSR);//读取网络状态寄存器的值
unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0; //检查载体是否在设备上,即检查链接状态
unsigned new_carrier;

new_carrier = (nsr & NSR_LINKST) ? 1 : 0;  //若链接上则为1,否则为0

if (old_carrier != new_carrier) {
if (netif_msg_link(db))//是否链接上
dm9000_show_carrier(db, new_carrier, nsr);//如果脸上了,显示一些网络link后的信息,如速度,全\半双工

if (!new_carrier)
netif_carrier_off(ndev);//没连上则clear carrier
else
netif_carrier_on(ndev);//连上了则set carrier
}
} else
mii_check_media(&db->mii, netif_msg_link(db), 0);//检测双工模式是否改变
if (netif_running(ndev))//检测设备是否被启动了
dm9000_schedule_poll(db);//关于这个函数我们在注释二里要好好说道说道
}

注释一:
struct delayed_work {
struct work_struct work;
struct timer_list timer;
};
container_of(w, struct delayed_work, work)这行代码的含义就是一个地址减去它在结构体struct delayed_work中偏移量,从而得到struct delayed_work结构体的入口地址。这个函数里面有三个参数,第一个是地址,第二个是结构体类型,第三个是结构体里成员的名字。实现的功能就是由结构体的成员得到整个结构体的指针。

注释二:在dm9000_probe函数中有过这么一句代码:INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);这行代码的含义就是用于初始化一个任务dm9000_poll_work,将db->phy_poll结构体中的work指向dm9000_poll_work;
 之后如果希望调用dm9000_poll_work这个函数,只需要用一句schedule_delayed_work()就可以了,那么什么时候调用函数schedule_delayed_work呢,我们在函数dm9000_interrupt和dm9000_schedule_poll中发现了答案;中断中要求1个延时后调用schedule_delayed_work,即dm9000_poll_work函数来检测并显示网络信息,而dm9000_schedule_poll只是对于TYPE_DM9000E类型的网卡进行了一个HZ*2的延时调用。那么dm9000_schedule_poll什么时候被调用呢,函数dm9000_open和dm9000_poll_work中都存在。我们再来总结一下,我们在本函数中调用了函数dm9000_schedule_poll,在dm9000_schedule_poll中调用了schedule_delayed_work函数,而这个函数又可以让函数dm9000_poll_work得到执行,那么只要网络是up的,dm9000_poll_work每隔一段时间就会执行一次。