Linux网卡驱动程序详解

来源:Linux认证    发布时间:2012-11-10    Linux认证视频    评论


ether_input(&sc->arpcom.ac_if,eh,m);/*传输给上一层的包括ifnet结构,以太网头部,一mbuf*/
}
/* 中断例程 */
static void
elintr(int unit)
{
register struct el_softc *sc;
register int base;
int stat, rxstat, len, done;
/* 寻址softc和I/O基地址 */
sc = &el_softc[unit];
base = sc->el_base;
dprintf(("elintr: "));
/* 检查板卡状态 */
stat = inb(base+EL_AS);
if(stat & EL_AS_RXBUSY) {/*接收忙*/
(void)inb(base+EL_RXC);/*读接收命令寄存器*/
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));/* 用IRQ(中断)使能和接收 写辅助命令寄存器*/
return;
}
done = 0;
while(!done) {
rxstat = inb(base+EL_RXS);
if(rxstat & EL_RXS_STALE) {/*EL_RXS_STALE代表接受状态没有改变*/
(void)inb(base+EL_RXC);/*读接收命令寄存器*/
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));/* 用IRQ(中断)使能和接收 写辅助命令寄存器*/
return;
}
/* 如果这有一个溢出发生,重新初始化板卡. */
if(!(rxstat & EL_RXS_NOFLOW)) {
dprintf(("overflow.n"));
el_hardreset(sc);
/* 使板卡回到接收模式 */
if(sc->arpcom.ac_if.if_flags & IFF_PROMISC)
outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
else
outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
(void)inb(base+EL_AS);/*读辅助状态寄存器*/
outb(base+EL_RBC,0);/*清除接收缓冲*/
(void)inb(base+EL_RXC);/*读接收命令寄存器*/
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));/* 用IRQ(中断)使能和接收 写辅助命令寄存器*/
return;
}
/* 到这应该是进来了一数据包 */
len = inb(base+EL_RBL);
len |= inb(base+EL_RBH) << 8;/*包长度的高低位组合为该包的长度*/
dprintf(("receive len=%d rxstat=%x ",len,rxstat));
outb(base+EL_AC,EL_AC_HOST);/*EL_AC_HOST为系统总线可访问缓冲 */
/* 如果包太短或太长,回到接收模式并返回
*/
if((len <= sizeof(struct ether_header)) || (len > ETHER_MAX_LEN)) {/*如果包小于以太网头部的长度或大于最大长度*/
if(sc->arpcom.ac_if.if_flags & IFF_PROMISC)/*为重置硬件准备if_flags*/
outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
else
outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW));
(void)inb(base+EL_AS);/*读辅助状态寄存器*/
outb(base+EL_RBC,0);/*清除接收缓冲*/
(void)inb(base+EL_RXC);/*读接收命令寄存器*/
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));/* 用IRQ(中断)使能和接收 写辅助命令寄存器*/
return;
}
sc->arpcom.ac_if.if_ipackets++;/*统计使用,说明接收包总数*/
/* 拷贝数据到我们的缓冲 */
outb(base+EL_GPBL,0);
outb(base+EL_GPBH,0);
insb(base+EL_BUF,sc->el_pktbuf,len);/*从端口读一串数据到指定地址()*/
outb(base+EL_RBC,0);
outb(base+EL_AC,EL_AC_RX);
dprintf(("m-->",sc->el_pktbuf+6,":"));/*也放置到el_pktbuf中,发送也放在他中,在发送时有一个开中断接数据包的过程不过那时候el_pktbuf中没有数据,不会相互影响.*/
dprintf(("mn",sc->el_pktbuf,":"));
/* 把数据传递到上一层 */
len -= sizeof(struct ether_header);
elread(sc,(caddr_t)(sc->el_pktbuf),len);
/* 对状态? */
stat = inb(base+EL_AS);
/* 如果忙不为真则继续 */
if(!(stat & EL_AS_RXBUSY))
dprintf((" "));
else
done = 1; /*退出循环*/
}
(void)inb(base+EL_RXC);
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));
return;
}

视频学习

我考网版权与免责声明

① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;

② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。

最近更新

社区交流

考试问答