第1页共49页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第1页共49页网卡设备驱动1.8139too网卡设备简介一个PCI设备,总共有三个地址空间:内存,端口和配置。内存和端口其实是同一个内容的不同访问路径而已。PCI设备的配置空间是标准化的,每个PCI设备的配置空间的前64个字节的含义都是一样的。但各个设备的内存和端口空间是完全不一样的。在硬件概念上设备的I/O内存和I/O端口空间没有区别,其实都是设备拥用的一些读写寄存器。8139too网卡拥有256字节的读写寄存器空间。它的整个布局如下:/*Symbolicoffsetstoregisters.*/enumRTL8139_registers{MAC0=0,/*Ethernethardwareaddress.*/MAR0=8,/*Multicastfilter.*/TxStatus0=0x10,/*Transmitstatus(Four32bitregisters).*/TxAddr0=0x20,/*Txdescriptors(alsofour32bit).*/RxBuf=0x30,ChipCmd=0x37,RxBufPtr=0x38,RxBufAddr=0x3A,IntrMask=0x3C,IntrStatus=0x3E,TxConfig=0x40,RxConfig=0x44,Timer=0x48,/*Ageneral-purposecounter.*/RxMissed=0x4C,/*24bitsvalid,writeclears.*/Cfg9346=0x50,Config0=0x51,Config1=0x52,FlashReg=0x54,MediaStatus=0x58,Config3=0x59,Config4=0x5A,/*absentonRTL-8139A*/HltClk=0x5B,MultiIntr=0x5C,TxSummary=0x60,BasicModeCtrl=0x62,BasicModeStatus=0x64,NWayAdvert=0x66,NWayLPAR=0x68,NWayExpansion=0x6A,/*Undocumentedregisters,butrequiredforproperoperation.*/FIFOTMS=0x70,/*FIFOControlandtest.*/CSCR=0x74,/*ChipStatusandConfigurationRegister.*/第2页共49页第1页共49页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第2页共49页PARA78=0x78,PARA7c=0x7c,/*Magictransceiverparameterregister.*/Config5=0xD8,/*absentonRTL-8139A*/};每个寄存器都有它特殊的含义和用途。举个例子(我们假设使用I/O内存的方式,ioaddr为设备内存映射在CPU内存地址空间的起始地址,下述代码能读取板卡的版本号):#defineHW_REVID(b30,b29,b28,b27,b26,b23,b22)\(b30<<30|b29<<29|b28<<28|b27<<27|b26<<26|b23<<23|b22<<22)#defineHW_REVID_MASKHW_REVID(1,1,1,1,1,1,1)/*identifychipattachedtoboard*/version=ioread32(ioaddr+TxConfig)&HW_REVID_MASK;在我的电脑上,version读出来的值的0x74400000,经过比对,板卡名称为:RTL-8100B/8139D。下面是整个系例版本号的表格:enumchip_flags{HasHltClk=(1<<0),HasLWake=(1<<1),};/*directlyindexedbychip_t,above*/conststaticstruct{constchar*name;u32version;/*fromRTL8139C/RTL8139Ddocs*/u32flags;}rtl_chip_info[]={{"RTL-8139",HW_REVID(1,0,0,0,0,0,0),HasHltClk,},{"RTL-8139revK",HW_REVID(1,1,0,0,0,0,0),HasHltClk,},{"RTL-8139A",HW_REVID(1,1,1,0,0,0,0),HasHltClk,},{"RTL-8139ArevG",HW_REVID(1,1,1,0,0,1,0),HasHltClk,},{"RTL-8139B",HW_REVID(1,1,1,1,0,0,0),HasLWake,},{"RTL-8130",HW_REVID(1,1,1,1,1,0,0),HasLWake,},{"RTL-8139C",HW_REVID(1,1,1,0,1,0,0),HasLWake,},{"RTL-8100",HW_REVID(1,1,1,1,0,1,0),HasLWake,},{"RTL-8100B/8139D",HW_REVID(1,1,1,0,1,0,1),HasLWake,},{"RTL-8101",HW_REVID(1,1,1,0,1,1,1),HasLWake,},};在这个表格中,RTL_8139B以下(包括RTL_8139B)的板卡都属于较新的版本。新老版本之间有不同的唤醒方式。先看新版本的:#defineLWAKE0x10#defineCfg1_PM_Enable0x01u8new_tmp8,tmp8;enumConfig4Bits{LWPTN=(1<<2),/*noton8139,8139A*/第3页共49页第2页共49页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第3页共49页};enumCfg9346Bits{Cfg9346_Lock=0x00,Cfg9346_Unlock=0xC0,};new_tmp8=tmp8=ioread8(ioaddr+Config1);if((rtl_chip_info[tp->chipset].flags&HasLWake)&&(tmp8&LWAKE))new_tmp8&=~LWAKE;new_tmp8|=Cfg1_PM_Enable;if(new_tmp8!=tmp8){iowrite8(Cfg9346_Unlock,ioaddr+Cfg9346);iowrite8(tmp8,ioaddr+Config1);iowrite8(Cfg9346_Lock,ioaddr+Cfg9346);}if(rtl_chip_info[tp->chipset].flags&HasLWake){tmp8=ioread8(ioaddr+Conf...