Linux网卡驱动程序详解

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


/* 调用通用以太网初始化例程 */
dprintf(("Attaching interface...n"));
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
/*
在if_ethersubr.c中的ether_ifattach例程
void ether_ifattach(ifp, bpf) 调用时,ETHER_BPF_SUPPORTED是BSD的包过滤器,如果在编译时设置文件没有打开包过滤器,那么代表0,否则是1
register struct ifnet *ifp;
int bpf;
{
register struct ifaddr *ifa;
register struct sockaddr_dl *sdl;
if_attach(ifp); 此例程在if.c 中
ifp->if_type = IFT_ETHER;代表以太网
ifp->if_addrlen = 6;硬件地址长度是6
ifp->if_hdrlen = 14;包的头长度是6+6+2=14,其中2是协议类型
ifp->if_mtu = ETHERMTU; 为1500,多此一举,在前面你可看到,已经填充了.
ifp->if_resolvemulti = ether_resolvemulti; 以太网解析多播例程指针
if (ifp->if_baudrate == 0) 波特率
ifp->if_baudrate = 10000000;
ifa = ifnet_addrs[ifp->if_index - 1];在ifnet_addrs[]数组中找到本地址指针
KASSERT(ifa != NULL, ("%s: no lladdr!n", __FUNCTION__));
sdl = (struct sockaddr_dl *)ifa->ifa_addr; ifa->ifa_addr在此时指向的是sockaddr_dl结构.
sdl->sdl_type = IFT_ETHER;
sdl->sdl_alen = ifp->if_addrlen;
bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);把硬件地址拷贝到sdl结构中if (bpf) bpf为真,即加入了BSD包过滤
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
if (ng_ether_attach_p != NULL)
(*ng_ether_attach_p)(ifp);
}
*/
printf("el%d: 3c501 address mn",idev->id_unit,
sc->arpcom.ac_enaddr, ":");
dprintf(("el_attach() finished.n"));
return(1);
}
/* 该例程重设接口. 在el_watchdog()中调用,因为watchdog不在本驱动程序中支持,所以从不被调用*/
static void
el_reset(xsc)/*上面的一个函数,重设硬件*/
void *xsc;
{
struct el_softc *sc = xsc;
int s;
dprintf(("elreset()n"));
s = splimp();/*关网络中断*/
el_stop(sc);/*下面的一个函数*/
el_init(sc);/*重新初始化卡*/
splx(s);/*开网络中断*/
}
/*停止接口,在el_ioctl()和el_reset()中调用*/
static void el_stop(xsc)
void *xsc;
{
struct el_softc *sc = xsc;
outb(sc->el_base+EL_AC,0);/*用0写辅助命令寄存器*/
}
/* 初始化接口. */
static void
el_init(xsc)
void *xsc;
{
struct el_softc *sc = xsc;
struct ifnet *ifp;
int s;
u_short base;
ifp = &sc->arpcom.ac_if;/*定位ifnet结构*/
base = sc->el_base;/*网卡基本I/O地址*/
/* 如果地址不知道,什么也不做. */
if(TAILQ_EMPTY(&ifp->if_addrhead)) /* 在if.c中的if_attach例程中已经填充,由el_attach调用
ether_attach时再调用if_attach */
return;
s = splimp();/*关网络中断*/

/* 重设板卡. */
dprintf(("Resetting board...n"));
el_hardreset(sc);/*该函数在上面,重设硬件*/
/* 设置接收寄存器 rx */
dprintf(("Configuring rx...n"));
if(ifp->if_flags & IFF_PROMISC) /*是混杂模式?EL_RXC是0X6接收命令寄存器*/
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));
outb(base+EL_RBC,0);/*接收缓冲寄存器清0*/
/* 设置传输寄存器 TX */
dprintf(("Configuring tx...n"));
outb(base+EL_TXC,0);
/* 开始接收 */
dprintf(("Starting reception...n"));
outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX));/*EL_AC_IRQE是IRQ enable(可用) EL_AC_RX为接收寄存器*/
/* 设置一些开始使用的标志 */
ifp->if_flags |= IFF_RUNNING;/*加上正在运行标志*/
ifp->if_flags &= ~IFF_OACTIVE;/*去掉正在传输标志*/
/* 调用输出. */
el_start(ifp);
splx(s);/*开网络中断*/

视频学习

我考网版权与免责声明

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

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

最近更新

社区交流

考试问答