|
網(wǎng)卡里一個(gè)概念叫descripter,它是DMA和CPU交換控制的一個(gè)固定結(jié)構(gòu)鏈表。
在初始化的時(shí)候,申請(qǐng)一定數(shù)目的和descripter的結(jié)構(gòu)一樣大小的內(nèi)存給網(wǎng)卡。對(duì)于收包方向上,還要申請(qǐng)同樣數(shù)目的packet buffer掛在這些descripter上。發(fā)包方向上,只在要發(fā)包的時(shí)候把要發(fā)送的這個(gè)packet buffer掛在當(dāng)前的descripter上,初始化的時(shí)候并不需要申請(qǐng)。
初始化還需要對(duì)descripter做一些必要的設(shè)置。完成以后,在收包方向,只要把這些descripter的控制權(quán)從CPU交到DMA的手上,然后DMA負(fù)責(zé)檢測網(wǎng)絡(luò)上有沒有包進(jìn)來,如果有,會(huì)根據(jù)設(shè)定做一些檢查,沒有問題就把這個(gè)包復(fù)制到第一個(gè)descripter 里面所帶的packet buffer里,產(chǎn)生一個(gè)信號(hào)通知CPU(一般是interrupt)同時(shí)也把這個(gè)descripter的控制權(quán)交給CPU,DMA自己會(huì)跳到下一個(gè)descripter上繼續(xù)同樣的監(jiān)測。一般這個(gè)鏈表是環(huán)行的,所以到底以后可以從頭再開始,也有的網(wǎng)卡會(huì)記住哪個(gè)是第一個(gè)哪個(gè)是最后一個(gè),自己做跳轉(zhuǎn)。 另外一端,CPU如果接收到interrupt或者自己loop查詢時(shí),發(fā)現(xiàn)有descripter的控制權(quán)是自己時(shí),就要去把這個(gè)packet buffer取出來,這里可以把內(nèi)容復(fù)制出來,也可以用一個(gè)新的把這個(gè)packet buffer替換掉,(在descripter里記錄只是buffer的指針),很明顯這種替換的做法,效率很高,這就是所謂“Zero copy”。當(dāng)然也有些網(wǎng)卡像realtek 8139系列就沒辦法做到這一點(diǎn)。因?yàn)橐驗(yàn)樗膁escripter 和packet buffer是連在一起的連續(xù)空間。
發(fā)包方向,初始化時(shí)只要descripter填些默認(rèn)值就可以了。在要發(fā)包的時(shí)候,才去做具體的事情,包括把packet buffer鏈到descripter上,再對(duì)descripter做必要設(shè)置,然后就把控制權(quán)交給DMA去處理。DMA發(fā)現(xiàn)這個(gè)descripter的控制者是自己,就會(huì)把這里packet buffer里面的內(nèi)容發(fā)送出去。發(fā)送完畢也會(huì)發(fā)個(gè)interrupt信號(hào)給cpu,然后把控制權(quán)還給cpu。CPU收到這個(gè)發(fā)送完成的interrupt,就會(huì)把這個(gè)packet buffer free掉。這里也是"Zero copy"的機(jī)制。另外一種做法是在初始化也和接收一樣同樣也申請(qǐng)packet buffer給descripter,在發(fā)送的時(shí)候需要把要發(fā)送的內(nèi)容復(fù)制到這個(gè)packet buffer里,然后發(fā)送完成后,就不需要對(duì)這個(gè)packet buffer做什么特別的事情了。
大概的原理就是這樣的,當(dāng)然還有其他許多東西比如flow control可以再做深入了解,而且每顆芯片都不太一樣,需要結(jié)合datasheet具體去處理。
無線網(wǎng)卡硬件實(shí)現(xiàn)和有線網(wǎng)卡差別很大,但是他的驅(qū)動(dòng)原理其實(shí)和有線網(wǎng)卡是一樣的,只是多了個(gè)RF的模塊而已。 |
|
【收藏】【打印】【進(jìn)入論壇】 |
|
|
|
|
|
|
|