收藏 分享(赏)

网卡设备驱动.docx

上传人:风样花鼓 文档编号:21098158 上传时间:2023-07-06 格式:DOCX 页数:47 大小:41.16KB
下载 相关 举报
网卡设备驱动.docx_第1页
第1页 / 共47页
网卡设备驱动.docx_第2页
第2页 / 共47页
网卡设备驱动.docx_第3页
第3页 / 共47页
亲,该文档总共47页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

1、网卡设备驱动1. 8139too网卡设备简介一个PCI设备,总共有三个地址空间:内存,端口和配置。内存和端口其实是同一个内容的不同访问路径而已。PCI设备的配置空间是标准化的,每个PCI设备的配置空间的前64个字节的含义都是一样的。但各个设备的内存和端口空间是完全不一样的。在硬件概念上,设备的I/O内存和I/O端口空间没有区别,其实都是设备拥用的一些读写寄存器。 8139too网卡拥有256字节的读写寄存器空间。它的整个布局如下: /* Symbolic offsets to registers. */ enum RTL8139_registers MAC0 = 0, /* Ethernet

2、hardware address. */ MAR0 = 8, /* Multicast filter. */ TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */ TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */ RxBuf = 0x30, ChipCmd = 0x37, RxBufPtr = 0x38, RxBufAddr = 0x3A, IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, RxConfi

3、g = 0x44, Timer = 0x48, /* A general-purpose counter. */ RxMissed = 0x4C, /* 24 bits valid, write clears. */ Cfg9346 = 0x50, Config0 = 0x51, Config1 = 0x52, FlashReg = 0x54, MediaStatus = 0x58, Config3 = 0x59, Config4 = 0x5A, /* absent on RTL-8139A */ HltClk = 0x5B, MultiIntr = 0x5C, TxSummary = 0x6

4、0, BasicModeCtrl = 0x62, BasicModeStatus = 0x64, NWayAdvert = 0x66, NWayLPAR = 0x68, NWayExpansion = 0x6A, /* Undocumented registers, but required for proper operation. */ FIFOTMS = 0x70, /* FIFO Control and test. */ CSCR = 0x74, /* Chip Status and Configuration Register. */ PARA78 = 0x78, PARA7c =

5、0x7c, /* Magic transceiver parameter register. */ Config5 = 0xD8, /* absent on RTL-8139A */ ; 每个寄存器都有它特殊的含义和用途。举个例子(我们假设使用I/O内存的方式,ioaddr为设备内存映射在CPU内存地址空间的起始地址,下述代码能读取板卡的版本号): #define HW_REVID(b30, b29, b28, b27, b26, b23, b22) (b3030 | b2929 | b2828 | b2727 | b2626 | b2323 | b2222) #define HW_REVID

6、_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1) /* identify chip attached to board */ version = ioread32( ioaddr + TxConfig ) & HW_REVID_MASK; 在我的电脑上,version读出来的值的0x74400000,经过比对,板卡名称为:RTL-8100B/8139D。 下面是整个系例版本号的表格: enum chip_flags HasHltClk = (1 0), HasLWake = (1 1), ; /* directly indexed by chip_t, above */

7、const static struct const char *name; u32 version; /* from RTL8139C/RTL8139D docs */ u32 flags; rtl_chip_info = RTL-8139, HW_REVID(1, 0, 0, 0, 0, 0, 0),HasHltClk, RTL-8139 rev K, HW_REVID(1, 1, 0, 0, 0, 0, 0),HasHltClk, RTL-8139A, HW_REVID(1, 1, 1, 0, 0, 0, 0),HasHltClk, RTL-8139A rev G,HW_REVID(1,

8、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

9、-8101, HW_REVID(1, 1, 1, 0, 1, 1, 1),HasLWake, , ; 在这个表格中,RTL_8139B以下(包括RTL_8139B)的板卡都属于较新的版本。新老版本之间有不同的唤醒方式。先看新版本的: #define LWAKE 0x10 #define Cfg1_PM_Enable 0x01 u8 new_tmp8, tmp8; enum Config4Bits LWPTN = (1 chipset.flags & HasLWake) & (tmp8 & LWAKE) new_tmp8 &= LWAKE; new_tmp8 |= Cfg1_PM_Enable;

10、 if (new_tmp8 != tmp8) iowrite8( Cfg9346_Unlock, ioaddr + Cfg9346 ); iowrite8( tmp8, ioaddr + Config1 ); iowrite8( Cfg9346_Lock, ioaddr + Cfg9346 ); if (rtl_chip_infotp-chipset.flags & HasLWake) tmp8 = ioread8( ioaddr + Config4 ); if (tmp8 & LWPTN) iowrite8( Cfg9346_Unlock, ioaddr + Cfg9346 ); iowri

11、te8( tmp8 & LWPTN, ioaddr + Config4 ); iowrite8( Cfg9346_Lock, ioaddr + Cfg9346 ); 基本的一个流程是:如果板卡版本本身支持了HasLWake,而Config1中读出的值带有LWAKE,把Config1的值写回,并把Config4 中的LWPTN去除。而我的网卡中从Config1, Config4读取的值分别为0x8d, 0x88,所以,无需做任何操作。 下面是旧版本的唤醒方式: enum Config1Bits Cfg1_PM_Enable = 0x01, Cfg1_VPD_Enable = 0x02, Cfg1

12、_PIO = 0x04, Cfg1_MMIO = 0x08, LWAKE = 0x10, /* not on 8139, 8139A */ Cfg1_Driver_Load = 0x20, Cfg1_LED0 = 0x40, Cfg1_LED1 = 0x80, SLEEP = (1 1), /* only on 8139, 8139A */ PWRDN = (1 0; i-) barrier(); if (ioread8( ioaddr + ChipCmd ) & CmdReset) = 0) break; udelay (10); 写一个CmdReset命令到ChipCmd位置,等待该命令消

13、失,即可。 关于网卡的寄存器操作,还有一些,再进行过程中遇到时再介绍。2. 网络设备的初始化网络接口是字符设备,块设备之后的第三类标准Linux设备。网络驱动程序和其它内核模块一样,当被装载到正在运行的内核中时,它要请求资源并提供一些功能设施。网络驱动程序对每个新检测到的接口,会向全局的网络设备链表中插入一个数据结构。每个接口由一个net_device结构描述,这是一个很庞大的结构,在下面的描述中,我们会看到一些这个结构的成员。在8139too网卡的驱动程序中,我们看到alloc_etherdev动态分配了该结构,这是为以太网接口封装的一个分配函数:struct net_device *all

14、oc_etherdev(int sizeof_priv)return alloc_netdev(sizeof_priv, eth%d, ether_setup);EXPORT_SYMBOL(alloc_etherdev);真正用来实现网络设备接口分配的函数是alloc_netdev alloc_ehterdev的封装为以太网设备接口分配了形如“eth%d”的名字,同时,指定了一个ether_setup的初始化函数:void ether_setup(struct net_device *dev)dev-change_mtu = eth_change_mtu;dev-hard_header = e

15、th_header;dev-rebuild_header = eth_rebuild_header;dev-set_mac_address = eth_mac_addr;dev-hard_header_cache = eth_header_cache;dev-header_cache_update= eth_header_cache_update;dev-hard_header_parse = eth_header_parse;dev-type = ARPHRD_ETHER;dev-hard_header_len = ETH_HLEN;dev-mtu = 1500; /* eth_mtu */

16、dev-addr_len = ETH_ALEN;dev-tx_queue_len = 1000; /* Ethernet wants good queues */dev-flags = IFF_BROADCAST|IFF_MULTICAST;memset(dev-broadcast,0xFF, ETH_ALEN);EXPORT_SYMBOL(ether_setup);它为表示以太网设备接口的net_device结构进行了部分初始化,因为对以太网设备来讲,很多操作与属性是固定的,内核可以帮助完成。alloc_netdev分配sizeof(dev) + sizeof_priv的内核页,并调用初始化

17、函数。这些都是在PCI的探测函数中做的事情,在完成了网络设备接口的分配后,我们要访问PCI设备的一些资源。在能够访问PCI设备的任何资源之前,我们必须激活PCI设备:/* enable device (incl. PCI PM wakeup and hotplug setup) */rc = pci_enable_device (pdev);if (rc) goto err_out;激活PCI设备后,我们可以从PCI设备的配置空间读取6个I/O地址区域,在我们的例子程序中,是从8139网卡的第1个I/O地址区域读取I/O内存空间,然后调用pci_request_regions(pdev, 81

18、39too);进行I/O内存分配。该函数实际调用request_mem_region函数。接下来,进行一系例的板卡相关的初始化操作。最后,接着ether_setup的操作,我们要对net_device作一些自己的初始化操作:dev-open = rtl8139_open;dev-hard_start_xmit = rtl8139_start_xmit;dev-get_stats = rtl8139_get_stats;dev-stop = rtl8139_close;open函数会在网络设备接口被注册的时候被调用,hard_start_xmit在有数据需要传输的时候被调用,get_stats返

19、回网络接口的统计信息。以上三个成员如果没有被初始化,则在注册网络接口的时候会造成内核崩溃。最后一个stop会在网络接口被停掉的时候被调用。完成了这些初始化操作之后,我们就可以注册网络设备接口了,一旦注册完毕,网络设备接口就可以被使用了:i = register_netdev(dev);if(i) return i;register_netdev首先为网络设备接口分配一个名称(比如把eth%d替换为eth0)。然后将dev插入到一个叫做dev_base的网络设备全局链表中。下面是整个8139too网卡设备初始化代码:/* 8139_init.h* helinqiang* 2006-3-11*/#

20、ifndef RTL_8139_INIT_H#define RTL_8139_INIT_H#include /for struct pci_device_id#include /for MODULE_DEVICE_TABLE#include /for struct pci_driver#include #define DRV_NAME 8139too#define DRV_VERSION 0.9.27#define RTL8139_DRIVER_NAME DRV_NAME Fast Ethernet driver DRV_VERSIONtypedef enumRTL8139 = 0,RTL81

21、29,board_t;static struct pci_device_id rtl8139_pci_tbl = 0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x4033, 0x1360, PCI_ANY

22、_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1186, 0x1300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1186, 0x1340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x13d1, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1259, 0xa117, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1259, 0xa11e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RT

23、L8139 ,0x14ea, 0xab06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x14ea, 0xab07, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x11db, 0x1234, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1432, 0x9130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x02ac, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x018a, 0x0106, PC

24、I_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,#ifdef CONFIG_SH_SECUREEDGE5410/* Bogus 8139 silicon reports 8129 without external PROM :-( */0x10

25、ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 ,#endif#ifdef CONFIG_8139TOO_81290x10ec, 0x8129, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8129 ,#endif/* some crazy cards report invalid vendor ids like* 0x0001 here. The other ids are valid and constant,* so we simply dont match on the main vendor id.*/PCI_

26、ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 ,PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, RTL8139 ,PCI_ANY_ID, 0x8139, 0x13d1, 0xab06, 0, 0, RTL8139 ,0,;MODULE_DEVICE_TABLE(pci, rtl8139_pci_tbl);static int _devinit rtl8139_init_one(struct pci_dev *pdev, const struct pci_device_id *id);static void _de

27、vexit rtl8139_remove_one(struct pci_dev *pdev);static int rtl8139_open( struct net_device *dev );static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev);static int rtl8139_close( struct net_device *dev );s

28、tatic void rtl8139_chip_reset (void _iomem *ioaddr);static int _devinit rtl8139_init_board (struct pci_dev *pdev,struct net_device *dev_out);static void _rtl8139_cleanup_dev (struct net_device *dev);static struct pci_driver rtl8139_pci_driver = .name = DRV_NAME,.id_table = rtl8139_pci_tbl,.probe = r

29、tl8139_init_one,.remove = _devexit_p(rtl8139_remove_one),;/* Bits in Config4 */enum Config4Bits LWPTN = (1 2), /* not on 8139, 8139A */;enum chip_flags HasHltClk = (1 0),HasLWake = (1 1),;enum ChipCmdBits CmdReset = 0x10,CmdRxEnb = 0x08,CmdTxEnb = 0x04,RxBufEmpty = 0x01,;enum Cfg9346Bits Cfg9346_Loc

30、k = 0x00,Cfg9346_Unlock = 0xC0,;typedef enum CH_8139 = 0,CH_8139_K,CH_8139A,CH_8139A_G,CH_8139B,CH_8130,CH_8139C,CH_8100,CH_8100B_8139D,CH_8101, chip_t;struct rtl8139_privatestruct pci_dev* pci_dev;void _iomem* mmio_addr;unsigned long regs_len;unsigned int chipset;struct net_device_stats stats;/* Sy

31、mbolic offsets to registers. */enum RTL8139_registers MAC0 = 0, /* Ethernet hardware address. */MAR0 = 8, /* Multicast filter. */TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */RxBuf = 0x30,ChipCmd = 0x37,RxBufPtr = 0x38,RxBufAddr

32、 = 0x3A,IntrMask = 0x3C,IntrStatus = 0x3E,TxConfig = 0x40,RxConfig = 0x44,Timer = 0x48, /* A general-purpose counter. */RxMissed = 0x4C, /* 24 bits valid, write clears. */Cfg9346 = 0x50,Config0 = 0x51,Config1 = 0x52,FlashReg = 0x54,MediaStatus = 0x58,Config3 = 0x59,Config4 = 0x5A, /* absent on RTL-8

33、139A */HltClk = 0x5B,MultiIntr = 0x5C,TxSummary = 0x60,BasicModeCtrl = 0x62,BasicModeStatus = 0x64,NWayAdvert = 0x66,NWayLPAR = 0x68,NWayExpansion = 0x6A,/* Undocumented registers, but required for proper operation. */FIFOTMS = 0x70, /* FIFO Control and test. */CSCR = 0x74, /* Chip Status and Config

34、uration Register. */PARA78 = 0x78,PARA7c = 0x7c, /* Magic transceiver parameter register. */Config5 = 0xD8, /* absent on RTL-8139A */;#define HW_REVID(b30, b29, b28, b27, b26, b23, b22) (b3030 | b2929 | b2828 | b2727 | b2626 | b2323 | b2222)#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)/* direc

35、tly indexed by chip_t, above */const static struct const char *name;u32 version; /* from RTL8139C/RTL8139D docs */u32 flags; rtl_chip_info = RTL-8139, HW_REVID(1, 0, 0, 0, 0, 0, 0),HasHltClk, RTL-8139 rev K, HW_REVID(1, 1, 0, 0, 0, 0, 0),HasHltClk, RTL-8139A, HW_REVID(1, 1, 1, 0, 0, 0, 0),HasHltClk,

36、 RTL-8139A rev G,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

37、, 0, 1, 0, 1),HasLWake, , RTL-8101, HW_REVID(1, 1, 1, 0, 1, 1, 1),HasLWake, ,;/* Bits in Config1 */enum Config1Bits Cfg1_PM_Enable = 0x01,Cfg1_VPD_Enable = 0x02,Cfg1_PIO = 0x04,Cfg1_MMIO = 0x08,LWAKE = 0x10, /* not on 8139, 8139A */Cfg1_Driver_Load = 0x20,Cfg1_LED0 = 0x40,Cfg1_LED1 = 0x80,SLEEP = (1

38、 1), /* only on 8139, 8139A */PWRDN = (1 0), /* only on 8139, 8139A */;#endif /RTL_8139_INIT_H/* 8139_init.c* helinqiang* 2006-3-11*/#include 8139_init.h#include #include #include #include MODULE_AUTHOR(Linqiang He, Hangzhou China);MODULE_LICENSE(Dual BSD/GPL);static int _init rtl8139_init_module(vo

39、id)/* when were a module, we always print a version message,* even if no 8139 board is found.*/#ifdef MODULEprintk (KERN_INFO RTL8139_DRIVER_NAME n);#endifreturn pci_module_init(&rtl8139_pci_driver);static void _exit rtl8139_cleanup_module (void)pci_unregister_driver(&rtl8139_pci_driver);module_init(rtl8139_init_module);module_exit(rtl8139_cleanup_module);int _devinit rtl8139_init_one(struct pci_dev *pde

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报