/* 第一次检查地址,看看基本地址是否在0X280到0X3F0之内 */
if((base < 0x280) || (base > 0x3f0)) {
printf("el%d: ioaddr must be between 0x280 and 0x3f0n",
idev->id_unit);
return(0);
}
/* 现在尝试从PROM中获取地址,看看是否包含了3COM供应商的标识代码.
*/
dprintf(("Probing 3c501 at 0x%x...n",base));/*在调试时会打印出*/
/* 重置板卡 */
dprintf(("Resetting board...n"));
outb(base EL_AC,EL_AC_RESET);/*我们一般定义基地址为0X300,EL_AC=0E,是辅助命令寄存器*/
DELAY(5);/*延迟5毫秒*/
outb(base EL_AC,0);
dprintf(("Reading station address...n"));
/* 读硬件地址,共六次 */
for(i=0;i
station_addr[i] = inb(base EL_EAW);/*EL_EAW是该卡的地址口,station_addr是函数内部变量,
下面判断了生产厂家后就没用的*/
}
dprintf(("Address is mn",station_addr, ":"));
/* 如果厂商标识代码正确,那么返回1.
*/
if((station_addr[0] != 0x02) || (station_addr[1] != 0x60)
|| (station_addr[2] != 0x8c)) {
dprintf(("Bad vendor code.n"));/*3COM厂商此种卡的代码为02608C*/
return(0);
} else {
dprintf(("Vendor code ok.n"));
/* 把地址拷贝到arpcom结构中 */
bcopy(station_addr,sc->arpcom.ac_enaddr,ETHER_ADDR_LEN);
return(1);
}
}
/* 这是一个子程序,目的是重设硬件. 在el_init()中调用,在elintr()中调用,产生中断,有溢出发生时调用*/
static __inline void
el_hardreset(xsc)
void *xsc;
{
register struct el_softc *sc = xsc;/*记住在C中,寄存器变量只能有三个,可加快速度*/
register int base;
register int j;
base = sc->el_base;
/* 第一步,重设板卡,和el_probe中的一样(前面) */
outb(base EL_AC,EL_AC_RESET);
DELAY(5);
outb(base EL_AC,0);
/* 又把地址填回去,为什么?没有为什么,就是厂商规定的,一些端口填什么数据时会怎么样,只有厂商知道,我相信,
在同一厂商之间的网卡,交换机,路由器进行秘密通讯是非常可能的,他可以不返回到CPU层*/
for(j=0;j
}
/* 连接该接口到核心数据结构.被调用时,我们已经知道该卡已经存在在给定的I/O
* 地址,我们还假定中断号是正确的.
*/
static int
el_attach(struct isa_device *idev)
{
struct el_softc *sc;
struct ifnet *ifp;/*该结构是一个巨大的结构,在STEVEN的书中有描述,我也写了一篇*/
u_short base;/*没用上,可以去掉*/
dprintf(("Attaching el%d...n",idev->id_unit));
/* 放置一些指针. */
idev->id_ointr = elintr;/*放置中断例程指针,中断例程在下面*/
sc = &el_softc[idev->id_unit];/*定位本设备的softc结构指针*/
ifp = &sc->arpcom.ac_if;/*定位ifnet结构*/
base = sc->el_base;/*从程序来看,这一句可以去掉,根本没用,因为在该函数中没用到base*/
/* 重设板卡 */
dprintf(("Resetting board...n"));
el_hardreset(sc);/*该程序在上面*/
/* 初始化ifnet结构,该结构的成员经常用来被ether网子程序,arp,bridge等调用 */
ifp->if_softc = sc;/*该网卡的IFP(通用接口结构)的专用结构指针(softc结构)*/
ifp->if_unit = idev->id_unit;/*第几块网卡*/
ifp->if_name = "el";/*网络卡的名称*/
ifp->if_mtu = ETHERMTU;/*1500*/
ifp->if_output = ether_output;/*以太网的输出子程序指针(不要搞错了,是向IP层
输出,按我们的理解是数据输入了,再转送到上一层协议)*/
ifp->if_start = el_start;/*把数据包从硬件接口输出去*/
ifp->if_ioctl = el_ioctl;/*控制网卡的函树指针*/
ifp->if_watchdog = el_watchdog;/*一般该函数用于包在一定时间内没发送出去,就调用他,在
本驱动程序中并不支持该函数,在我的rtl8139说明中有*/
ifp->if_init = el_init; /*不用说,是初始化,在probe,attach之后被调用*/
推荐阅读
- 2 FreeBSD 核心
- 在freebsd上安装linuxigd
- 一 FreeBSD服务器的安装与优化 ----附一个我的核心文件参考
- FreeBSD5.2中成功安装oracle9i手记
- FREEBSD中使用IPFW来过滤ICMP服务
- freebsd5.0kde中文界面设置
- 浅谈FreeBSD 5.2 常用操作
- FreeBSD 5.0 网关指南2.0. rc1
- 启用FreeBSD 5-CURRENT的ULE调度器
- FreeBSD 5内核源代码分析之copyin实现原理