首页>计算机>Linux认证>学习教程>正文
Linux网卡驱动程序详解

www.zige365.com 2008-8-19 15:40:09 点击:发送给好友 和学友门交流一下 收藏到我的会员中心
}
/* 开始在接口上输出.从队列中得到包并输出他们,在输出中,留出接收用一部分时间,即打开中断再关闭中断,这样使接口接到的一些数据包不会丢失.
*/
static void
el_start(struct ifnet *ifp)
{
struct el_softc *sc;
u_short base;
struct mbuf *m, *m0;
int s, i, len, retries, done;
/* 定位softc结构的指针*/
sc = ifp->if_softc;
base = sc->el_base;/*基地址在输入输出指令时常要用到*/
dprintf(("el_start()...n"));
s = splimp();/*因为下面涉及到if_flags的操作,所以要关闭网络中断*/
/* 如果输出正在进行,则退出 */
if(sc->arpcom.ac_if.if_flags & IFF_OACTIVE)
return;
sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;/*加上输出正在进行传输标志*/
/* 主循环
*/
while(1) {/*唯一出口是准备传输的数据为空,即m0==NULL时*/
/* 从队列中移出下一数据包到m0中,请看头文件if_var.h
#define IF_DEQUEUE(ifq, m) {
(m) = (ifq)->ifq_head; ifq是一mbuf指针队列,把第一个mbuf指针放到m中
if (m) {
if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) 重排队列
(ifq)->ifq_tail = 0;
(m)->m_nextpkt = 0;
(ifq)->ifq_len--;
}
}

*/
IF_DEQUEUE(&sc->arpcom.ac_if.if_snd,m0);/* &sc->arpcom.ac_if.if_snd指向发送队列,该宏取出第一个mubf的指针放到m0中,看上面的说明.
这是数据结构的好教材*/
/* 如果发送缓冲区指针为空,即已经发送完,则退出,此是该无穷循环的唯一出口. */
if(m0 == NULL) {
sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;/*出去前当然要去掉输出正在进行标志*/
splx(s);
return;
}
/* 关闭接收 */
outb(base+EL_AC,EL_AC_HOST);/*EL_AC_HOST为系统总线可访问缓冲,即系统总线网卡要用 */
outb(base+EL_RBC,0);/*接收缓冲寄存器清0*/
/* 拷贝mbuf中的数据到softc结构定义的成员el_pktbuf中,缓冲大小是EL_BUFSIZ即2048. */
len = 0;
for(m = m0; m != NULL; m = m->m_next) { /* m0是一mbuf指针,也是一mbuf链的第一个,此
次要发送的是一mbuf链,不是一单个mbuf*/
if(m->m_len == 0)
continue;
bcopy(mtod(m,caddr_t),sc->el_pktbuf+len,m->m_len);/*m->len是该mbuf链的数据长度,sc->el_pktbuf是该卡的发送临时缓冲,要发送的数据在这集中,然后传送到网卡上,太费时间了,应该直接放置到网卡的存储器中.*/
len += m->m_len; /*len是这次要发送的总数*/
}
m_freem(m0); /*释放该mbuf链*/
len = max(len,ETHER_MIN_LEN); /*ETHER_MIN_LEN是发送的最小长度*/
/* 如果有BPF,就交给BPF验证 */
if(sc->arpcom.ac_if.if_bpf)
bpf_tap(&sc->arpcom.ac_if, sc->el_pktbuf, len);/*你当然可以在这写一点自己的验证过程*/
/* 传送数据包到板卡 */
dprintf(("el: xfr pkt length=%d...n",len));
i = EL_BUFSIZ - len;/*EL_BUFSIZ=2048字节*/
outb(base+EL_GPBL,(i & 0xff)); /*告诉发送的长度*/
outb(base+EL_GPBH,((i>>&0xff));
outsb(base+EL_BUF,sc->el_pktbuf,len);/*传输数据到板卡*/
/* 开始发送数据包 */
retries=0;/*下面做循环用的,在发不出去时,循环15次*/
done=0; /*done=1时发送成功了*/
while(!done) {
if(el_xmit(sc,len)) { /* 调用发送例程,其实只要传送base就可以了 */
done = -1;
break;
}

本新闻共9页,当前在第5页  1  2  3  4  5  6  7  8  9  

我要投稿 新闻来源: 编辑: 作者:
相关新闻
红旗linux认证工程师考题系统部份(3)
Wine让Windows上的软件集体移民
Linux启动过程全接触
LinuxDNS的负载均衡及子域委派
用chkconfig轻松管理启动程序
如何设置Ubuntu做网关