id_unit); return(0); } /* 現(xiàn)在嘗試從PRO。1 freebsd網(wǎng)卡驅(qū)動程序詳解( 三 )。" />

日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

1 freebsd網(wǎng)卡驅(qū)動程序詳解( 三 )



/* 第一次檢查地址,看看基本地址是否在0X280到0X3F0之內(nèi) */
if((base < 0x280) || (base > 0x3f0)) {
printf("el%d: ioaddr must be between 0x280 and 0x3f0n",
idev->id_unit);
return(0);
}

/* 現(xiàn)在嘗試從PROM中獲取地址,看看是否包含了3COM供應商的標識代碼.
*/
dprintf(("Probing 3c501 at 0x%x...n",base));/*在調(diào)試時會打印出*/

/* 重置板卡 */
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[i] = inb(base EL_EAW);/*EL_EAW是該卡的地址口,station_addr是函數(shù)內(nèi)部變量,
下面判斷了生產(chǎn)廠家后就沒用的*/
}
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結(jié)構(gòu)中 */
bcopy(station_addr,sc->arpcom.ac_enaddr,ETHER_ADDR_LEN);
return(1);
}
}

/* 這是一個子程序,目的是重設硬件. 在el_init()中調(diào)用,在elintr()中調(diào)用,產(chǎn)生中斷,有溢出發(fā)生時調(diào)用*/
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);

/* 又把地址填回去,為什么?沒有為什么,就是廠商規(guī)定的,一些端口填什么數(shù)據(jù)時會怎么樣,只有廠商知道,我相信,
在同一廠商之間的網(wǎng)卡,交換機,路由器進行秘密通訊是非??赡艿?他可以不返回到CPU層*/
for(j=0;joutb(base j,sc->arpcom.ac_enaddr[j]);
}

/* 連接該接口到核心數(shù)據(jù)結(jié)構(gòu).被調(diào)用時,我們已經(jīng)知道該卡已經(jīng)存在在給定的I/O
* 地址,我們還假定中斷號是正確的.
*/
static int
el_attach(struct isa_device *idev)
{
struct el_softc *sc;
struct ifnet *ifp;/*該結(jié)構(gòu)是一個巨大的結(jié)構(gòu),在STEVEN的書中有描述,我也寫了一篇*/
u_short base;/*沒用上,可以去掉*/

dprintf(("Attaching el%d...n",idev->id_unit));

/* 放置一些指針. */
idev->id_ointr = elintr;/*放置中斷例程指針,中斷例程在下面*/
sc = &el_softc[idev->id_unit];/*定位本設備的softc結(jié)構(gòu)指針*/
ifp = &sc->arpcom.ac_if;/*定位ifnet結(jié)構(gòu)*/
base = sc->el_base;/*從程序來看,這一句可以去掉,根本沒用,因為在該函數(shù)中沒用到base*/

/* 重設板卡 */
dprintf(("Resetting board...n"));
el_hardreset(sc);/*該程序在上面*/

/* 初始化ifnet結(jié)構(gòu),該結(jié)構(gòu)的成員經(jīng)常用來被ether網(wǎng)子程序,arp,bridge等調(diào)用 */
ifp->if_softc = sc;/*該網(wǎng)卡的IFP(通用接口結(jié)構(gòu))的專用結(jié)構(gòu)指針(softc結(jié)構(gòu))*/
ifp->if_unit = idev->id_unit;/*第幾塊網(wǎng)卡*/
ifp->if_name = "el";/*網(wǎng)絡卡的名稱*/
ifp->if_mtu = ETHERMTU;/*1500*/
ifp->if_output = ether_output;/*以太網(wǎng)的輸出子程序指針(不要搞錯了,是向IP層
輸出,按我們的理解是數(shù)據(jù)輸入了,再轉(zhuǎn)送到上一層協(xié)議)*/
ifp->if_start = el_start;/*把數(shù)據(jù)包從硬件接口輸出去*/
ifp->if_ioctl = el_ioctl;/*控制網(wǎng)卡的函樹指針*/
ifp->if_watchdog = el_watchdog;/*一般該函數(shù)用于包在一定時間內(nèi)沒發(fā)送出去,就調(diào)用他,在
本驅(qū)動程序中并不支持該函數(shù),在我的rtl8139說明中有*/
ifp->if_init = el_init; /*不用說,是初始化,在probe,attach之后被調(diào)用*/

推薦閱讀