📄 网卡驱动程序详解.doc
字号:
<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=gb2312">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 10">
<meta name=Originator content="Microsoft Word 10">
<link rel=File-List href="网卡驱动程序详解.files/filelist.xml">
<title>欢迎来到LinuxKit.com!!</title>
<!--[if gte mso 9]><xml>
<o:DocumentProperties>
<o:Author>Lee</o:Author>
<o:Template>Normal</o:Template>
<o:LastAuthor>Lee</o:LastAuthor>
<o:Revision>4</o:Revision>
<o:TotalTime>2</o:TotalTime>
<o:Created>2004-10-06T06:52:00Z</o:Created>
<o:LastSaved>2004-10-06T06:54:00Z</o:LastSaved>
<o:Pages>9</o:Pages>
<o:Words>3250</o:Words>
<o:Characters>18525</o:Characters>
<o:Company>Lee</o:Company>
<o:Lines>154</o:Lines>
<o:Paragraphs>43</o:Paragraphs>
<o:CharactersWithSpaces>21732</o:CharactersWithSpaces>
<o:Version>10.4219</o:Version>
</o:DocumentProperties>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:Compatibility>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]-->
<link rel=Stylesheet type="text/css" media=all href="inc/MAIN.CSS">
<style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:宋体;
mso-bidi-font-family:宋体;}
@page Section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style>
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";}
</style>
<![endif]--><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026"/>
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1"/>
</o:shapelayout></xml><![endif]-->
</head>
<script language="JavaScript" type="text/JavaScript">
function validate(theform) {
if (theform.Content.value=="" || theform.Title.value=="") {
alert("请填写评论的内容.");
return false; }
}
</script>
<style type="text/css">
<!--
.stedit {
BORDER-BOTTOM: #4a3163 1px solid;
BORDER-LEFT: #4a3163 1px solid;
BORDER-RIGHT: #4a3163 1px solid;
BORDER-TOP: #4a3163 1px solid;
FONT-SIZE: 9pt;
}
.table1 {
BORDER-BOTTOM: #7D7D7D 1px solid; BORDER-LEFT: #7D7D7D 0px solid; BORDER-RIGHT: #7D7D7D 0px solid; BORDER-TOP: #7D7D7D 1px solid
}
-->
</style>
<body bgcolor=white background="image/bg.gif" lang=ZH-CN link=blue vlink=blue
style='tab-interval:21.0pt' leftmargin=0 topmargin=0>
<div class=Section1>
<p class=MsoNormal><span lang=EN-US style='display:none;mso-hide:all'><o:p> </o:p></span></p>
<div align=center>
<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0
style='mso-cellspacing:0cm;background:white;mso-padding-alt:0cm 0cm 0cm 0cm'
witdth="100%" height=542 borderlightcolor="#EBF1F1" bordercolordark="#e2dffd">
<tr style='mso-yfti-irow:0;mso-yfti-lastrow:yes;height:203.25pt'>
<td width=776 valign=top style='width:582.3pt;padding:0cm 0cm 0cm 0cm;
height:203.25pt'>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<table class=MsoNormalTable border=0 cellpadding=0 width="100%"
style='width:100.0%;mso-cellspacing:1.5pt' background="image/point.gif">
<tr style='mso-yfti-irow:0;mso-yfti-lastrow:yes;height:26.25pt'>
<td style='padding:.75pt .75pt .75pt .75pt;height:26.25pt'>
<p class=MsoNormal align=center style='text-align:center'><strong><span
style='font-family:宋体;mso-bidi-font-family:宋体;color:black'>网卡驱动程序详解</span></strong>
</p>
</td>
</tr>
</table>
<p class=MsoNormal><span lang=EN-US style='display:none;mso-hide:all'><o:p> </o:p></span></p>
<div align=center>
<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width="95%"
style='width:95.0%;mso-cellspacing:0cm;mso-padding-alt:0cm 0cm 0cm 0cm'>
<tr style='mso-yfti-irow:0;mso-yfti-lastrow:yes;height:285.0pt'>
<td valign=top style='padding:0cm 0cm 0cm 0cm;height:285.0pt'>
<p class=MsoNormal style='margin-bottom:12.0pt'><span lang=EN-US><br>
<span style='color:#594802'>/* 注释:xie_minix */ <br>
/*此处为BSD申明,略过... 最好是拷贝下来用C的开发工具来看比较好*/ <br>
/* <br>
当网络上一台计算机准备发送数据时,他的网卡开始工作了,首先网卡的芯片侦听在网络上是否有数据在 <br>
流动,如果没有,他就把数据发送到网络上,在侦听和发送之间有一段极小的时间延迟,在这段时间内,也有 <br>
可能在网络上有其他的计算机也准备发送数据,也侦听到网络上没有数据在流动,这就可能两台甚至多台 <br>
的数据一起发送到网络上,产生数据的碰撞,发送数据的计算机的网卡芯片当然要在发送完成后再校验返回 <br>
的数据,如果发现和发送的数据不一致,那就是说产生了碰撞,所以在一个以太网络中的计算机数量不宜过多, <br>
他不但会增加广播包在网络中的数量,也请也会增加数据包的碰撞次数. <br>
我们的计算机的网卡芯片在接收到一完整的数据包后,芯片的一引脚通知8259中断控制器,中断控制器再 <br>
发出中断给CPU,由此,CPU随即调用该网卡的中断例程,如: <br>
DOS是这样的 <br>
屏蔽所有中断(cli) <br>
push any register <br>
因为中断向量在段0 <br>
所以xor ax,ax <br>
mov ds,ax <br>
mul ax,中断号 <br>
那么在数据段的[ax]偏移处是该中断例程的指针了 <br>
call [ax]就到该中断例程了 <br>
...(DOS是比较遥远的事情了,我所描述的是他的原理,当然不会这么简单,如果那位网友有兴趣详细描述一下 <br>
上面的原理,纠正或替换掉我所写的就感激不尽了) <br>
<br>
总之,在本例程中,CPU将调用elintr中断例程,并带有参数unit即该种网卡的第几块(因为在计算机中,你有可能 <br>
装了相同的网卡有几块),elintr的作用是把数据从网卡的数据存储器中读到我们在该网卡初始化时预先分配好 <br>
的数据缓冲区中,他调用的函数就只有elread,同样elread也只调用了elget一个函数.elread函数比较简单,就是 <br>
调用elget,elget则相对比较复杂一点,涉及到核心内存分配mbuf,mbuf是比较恐怖的东西,正如STEVEN所写的,为 <br>
了节约当时"巨大"的4M内存,牺牲了性能搞出了这个mbuf东东,mbuf是必须要弄懂的,虽然在设备驱动程序中调用 <br>
他的宏和函数不多,但在后面的IP协议,TCP协议中有不少涉及的地方. <br>
关于数据发送方面和接收差不多,在上层协议放置好数据到mbuf链后,调用el_start函数,该函数把mbuf链中 <br>
的数据放置到本块网卡的发送队列缓冲el_pktbuf中,然后再调用el_xmit函数,此函数把发送队列缓冲el_pktbuf <br>
中的数据有传递到网卡的数据存储器中.我认为,这中间的内存拷贝是多于的,应该在el_start函数中直接把mbuf <br>
中的数据传递到网卡的数据存储器中,这样会使性能有较大幅度的提升,因为在驱动程序设计时,最好减少大量的 <br>
内存拷贝,他占用的时间太多了. <br>
*/ <br>
<br>
/* FreeBSD的3COM以太网设备驱动程序 */ <br>
/*本段头文件是在编译核心时产生的*/ <br>
<br>
<br>
<br>
#include "el.h" /*此三文件为编译时产生的头文件,内容是定制核心的一些常量*/ <br>
#include "opt_inet.h" <br>
#include "opt_ipx.h" <br>
<br>
#include <sys/param.h> <br>
#include <sys/systm.h> <br>
#include <sys/sockio.h> <br>
#include <sys/mbuf.h> <br>
#include <sys/socket.h> <br>
#include <sys/syslog.h> <br>
<br>
#include <net/ethernet.h> <br>
#include <net/if.h> <br>
<br>
#include <netinet/in.h> <br>
#include <netinet/if_ether.h> <br>
<br>
#include <net/bpf.h> <br>
<br>
#include <machine/clock.h> <br>
<br>
#include <i386/isa/isa_device.h> <br>
#include <i386/isa/if_elreg.h>/*此头文件是3COM卡的寄存器常量*/ <br>
<br>
/* 为了调试方便 */ <br>
#ifdef EL_DEBUG <br>
#define dprintf(x) printf x /*如果定义了DEBUG调试,则打印到屏幕*/ <br>
#else <br>
#define dprintf(x) <br>
#endif <br>
<br>
/* softc结构,每种网卡的该结构是不同的,主要是该第一个成员必须是一以太网的共用结构arpcom*/ <br>
static struct el_softc { <br>
struct arpcom arpcom; /* 以太网公共部分 */ <br>
u_short el_base; /* 基本输入输出地址 */ <br>
char el_pktbuf[EL_BUFSIZ]; /* 帧缓冲大小2048 */ <br>
} el_softc[NEL]; /*NEL在el.h中定义,即编译时产生的头文件,意思为支持的网卡数*/ <br>
/* <br>
看看arpcom结构吧 <br>
<br>
* 该结构是以太网设备驱动程序和ARP程序所共享. <br>
<br>
struct arpcom { <br>
/* <br>
* ifnet 结构必须在此结构的第一个位置. <br>
/ <br>
struct ifnet ac_if; <br>
u_char ac_enaddr[6]; /* 以太网硬件地址/ <br>
int ac_multicnt; /* 多播地址列表数 / <br>
void *ac_netgraph; /* netgraph 节点信息,即我们所说的PPPoE,也就是ADSL宽带所用到的 / <br>
}; <br>
<br>
<br>
*/ <br>
<br>
/* 一些函数申明 */ <br>
static int el_attach(struct isa_device *);/*第二步:填充相关的数据结构*/ <br>
static void el_init(void *); /*不用说,是初始化,在probe,attach之后被调用*/ <br>
static int el_ioctl(struct ifnet *,u_long,caddr_t);/*控制网卡的函树指针*/ <br>
static int el_probe(struct isa_device *);/*第一步:探测程序.查看是否卡存在和是否在正确的位置.*/ <br>
static void el_start(struct ifnet *);/*把数据包从硬件接口输出去*/ <br>
static void el_reset(void *);/* 该例程重设接口. 在el_watchdog()中调用*/ <br>
static void el_watchdog(struct ifnet *);/*一般该函数用于包在一定时间内没发送出去,就调用他,在 <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -