/* 现在尝试从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;ioutb(base+EL_GPBL,i); station_addr = 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;joutb(base+j,sc->arpcom.ac_enaddr[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之后被调用*/ ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX);/*支持广播和单播*/ |