分类: BSD
2008-04-07 18:12:41
printf("rl%d: watchdog timeout\n", sc->rl_unit);
/*打印出是哪块网卡出现问题。
sc->rl_unit代表该种网卡的第几快。我们知道在一个机器里同样
的网卡可能有几块,当然此参数是由网卡驱动程序的初始化程序
填充*/
ifp->if_oerrors++;
/*累计输出出现的错误包数量(o代表输出)*/
rl_txeof(sc);
/*这里是每个驱动程序不同的,此处为8139的,不过我觉得用rl_stop(sc)更好*/
rl_rxeof(sc);
/*这里也是每个驱动程序不同。我觉得来一个rl_reset(sc)也不错。*/
rl_init(sc);/*这里大家都一样,重新初始芯片。*/
return;
}
if_slowtimo(arg)
void *arg;
{
struct timeout *to = (struct timeout *)arg;
struct ifnet *ifp;
int s = splimp();
/*在做以下操作的时候必须关中断*/
TAILQ_FOREACH(ifp, &ifnet, if_list)
{/*搜索每一个接口设备,TAILQ_FOREACH实际上是for(...)*/
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
/*如果是if_timer为0或if_timer减1以后还为真,实际上是对每块网卡
的计数器if_timer减1后判断他是否还大于0,小于0就调用watchdog
函数。*/
if (ifp->if_watchdog) /*不过调用之前看看该卡有没有watchdog函数*/
(*ifp->if_watchdog)(ifp);
}
splx(s);
timeout_add(to, hz /
IFNET_SLOWHZ);
/*每次计时器完成后都会清除,你不得不又加上去。hz是计算
机的主频,就是说调度的间隔时间是和主频成正比的关系。*/
}
struct ifnet *ifp;
{
struct rl_softc *sc;
struct mbuf *m_head = NULL;
sc = ifp->if_softc;
while(RL_CUR_TXMBUF(sc) == NULL) {/* 1:当输出缓冲区为空时才进行新的输出*/
IF_DEQUEUE(&ifp->if_snd, m_head);/*把将要输出的数据加入到输出队列中。*/
if (m_head == NULL)/* 2:申请内存失败*/
break;
if (rl_encap(sc, m_head))
{/*8139卡的弱智表现在此,多加一个头部,还要长字节对齐,影响
到数据必须重新搬迁。花时间啊!*/
IF_PREPEND(&ifp->if_snd, m_head);
ifp->if_flags |= IFF_OACTIVE;
break;
}
if (ifp->if_bpf)/* 3:如果包过滤存在就进行过滤*/
bpf_mtap(ifp, RL_CUR_TXMBUF(sc));
CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),/* 4:以下为硬件输出的IO指令*/
vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
RL_TXTHRESH(sc->rl_txthresh) |
RL_CUR_TXMBUF(sc)->m_pkthdr.len);
RL_INC(sc->rl_cdata.cur_tx);
}
if (RL_CUR_TXMBUF(sc) !=
NULL)/*如果传送缓冲不为空,说明数据放到缓冲中已经准备传了*/
ifp->if_flags |= IFF_OACTIVE;/*加上正在传标志*/
ifp->if_timer = 5;/*设定计数器为5*/
return;
}
{
... 这中间我就不写了
if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR))
/*如果中断后状态寄存器的标识 是成功或出错,就调用下面的程序。*/
rl_txeof(sc);
...
}
再看rl_txeof:
static void rl_txeof(sc)
{
...
ifp->if_timer =
0;
/*哈哈,在这清0了,也就是说,只要你不是反复在那传,
不管传输错误和传输正确 都不会出现"watchdog timeout"*/
...
}
在函数static void rl_start(ifp)中加入:
static void rl_start(ifp)
struct ifnet *ifp;
{
struct rl_softc *sc;
struct mbuf *m_head = NULL;
sc = ifp->if_softc;
u_int8_t tmperror;
if (RL_CUR_TXMBUF(sc) != NULL) {/*新加,如果是缓冲区不够问题*/
myerror=1;
}
while(RL_CUR_TXMBUF(sc) == NULL) {
IF_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
{
myerror=2; /*内存分配出错*/
break;
}
if (rl_encap(sc, m_head)) {
IF_PREPEND(&ifp->if_snd, m_head);
ifp->if_flags |= IFF_OACTIVE;
break;
}
if (ifp->if_bpf)
bpf_mtap(ifp, RL_CUR_TXMBUF(sc));
tmperror=myerror;/*在进行写IO口前先保存前面出错的原因*/
CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
RL_TXTHRESH(sc->rl_txthresh) |
RL_CUR_TXMBUF(sc)->m_pkthdr.len);
myerror=tmperror;/*上面两句没问题的话再还原前面的出错原因*/
RL_INC(sc->rl_cdata.cur_tx);
}
if (RL_CUR_TXMBUF(sc) != NULL)
ifp->if_flags |= IFF_OACTIVE;
ifp->if_timer = 5;
return;
}