Linux下网卡驱动程序

Linux下网卡驱动程序
Linux下网卡驱动程序

Linux下8019网卡驱动程序

福建鑫诺通信有限公司陈光平(chenggp_fj@https://www.360docs.net/doc/246579061.html,)

本文以S3C44B0的CPU为例,详细解析了linux下RTL8019网卡驱动程序工作原理,其间知识大多来源互联网络,特别是浙大潘纲的论文,在此不一一列出,此文目的只是让嵌入式linux爱好者得到更多网卡驱动的资料,并获得交流机会,不足之处请指正

(一)、硬件相关部份

1、CPU与网卡的连接方式

(s3c44B0 CPU) (RTL 8019网卡)

CPU与网卡接线图

上图为S3c44b0CPU和网卡的接线图,此接法并非固定,如接法不同,则牵涉到很多相应的改动,下面会详细分析不同之处

从硬件部门得到:网卡在CPU的存储空间上接BANK4,即0x08000000(看44B0手册)外部中断号为:EXTINT3 (irqs.h文件获得值为22)

上面两个值可以查CPU手册,或询问硬件设计人员

由上图可以知道以下数据:

(1)、网卡与CPU地址线连接错开8位(A0接A8)

(2)、总共连线,其实4根就足够用了,因为每根线可以译码4个地址空间,总共是16个地址空间,每个地址空间对应一个寄存器地址,而8019总共就是16个寄存器(3)、一般是跳线模式,不使用9346芯片

1-1 基地址算法

首先8019的基地址是300H(见RTL8019芯片资料:选择IO总线地址),但是有些硬件已在芯片中做过了偏移,比如我们的网卡已做了处理,基址已偏移到0x08000000,

那么因为网卡A0接CPU的A8,表示基地址左移8位,下一个寄存器reg0的地址就是:0x08000100(0000,0000,0001 0001,0000,0000)

还不理解的话我们看另一种接法:

(S3C44B0 CPU ) (RTL8019芯片) 这种接法地址线只错开一位,我们来看(假如仍使用BANK4):

A1 A0,为何A0不能接A0,因为8019是共用数据线和地址线的,如果A0接A0的话,无法配置8位和16位方式

现在可以看到,基地址为300H 的话,左移一位(A0->A1),就是600H,于是算出基地址为: 0x08000600,下一个寄存器的地址就是

0x08000602,因为都左移一位,相当于x2了

2、8019网卡的工作原理

本节主要讨论一下

8019是怎么工作的,如下图:

(本地DMA ) (远端DMA )

(图2 与DMA 有关的寄存器 )

2-1 远端DMA 和本地DMA

首先解释一下远端DMA 和本地DMA 的区别,以发送为例,网络发送数据是下面这样一个流程:

CPU 将数据先发送到网卡上的16KRAM 中,这之间必须要有一个数据通道,我们称为远端DMA ,而数据从网卡的RAM 中发出给链路,RTL8019控制器与RAM 之间的通道称为本地DMA

2-2 CPU 读写数据到网络芯片

先解释一下上面提到的几个重要的寄存器,我们从上面分阶段说明:

RBCR0,RBCR1:存放要读写数据的长度

RSAR0,RSAR1:存放数据到网络芯片(RAM)中存放的起始地址(而不是页号,但通常还是以某页的00为开始,如0x4000)

CR:向命令寄存器发出Remote DMA开始指令

上面的流程后面会详细解说

2-3 网络芯片发数据到以太网

CPU把数据用Remote DMA发到网络芯片之后,就可以用让网络芯片用Local DMA向

外数据了,需要设置如下的控制器:

TPSR:网络芯片要发送的数据在网络芯片RAM中的起始页号,所以发送的数据只能从某页的开头存放。

TBCR0,TBCR1:要发送的数据总长度

CR:向命令寄存器发出发送数据包的指令CMD_XMIT

然后程序就可以返回了,网络芯片会自动用Local DMA发数据包

2-4 网络芯片从以太网读数据

网络芯片在从以太网读数据过程中,会用到的寄存器如下:

PSTART,PSTOP:网络芯片接收数据缓冲区的起始和终止页号。形成一个接收缓冲环,每页256字节

CURR:接收缓冲环写页指针,初始化=PSTART

BNRY:接收缓冲环读页指针,初始化=PSTART

这四个寄存器在init函数里初始化,以后有数据包来到时,网络芯片会自动判断是否发给本机,是则用Local DMA存入数据,并自动修改读写指针

RTL8019接收包帧结构:

具体流程如下:

有了上面的收发包的格式,如何发送和接收数据包呢?看下图:

图3 发送缓冲区

先将待发送的数据包存入芯片RAM,给出发送缓冲区首地址和数据包长度(写入TPSR,TBCR0,1),启动发送命令(CR=3E),即可实现8019发送功能.8019会自动按以太网协议完成发送并将结果写入状态寄存器。

那么8019是怎样接收数据的呢?请看下图:

接收缓冲区构成一个循环FIFO队列,PSTART、PSTOP两个寄存器限定了循环队列的开始和结束页,CURR为写入指针,受芯片控制,BNRY为读出指针,由主机程序控制,根据CURR=BNRY+1?可以判断是否收到新的包,新收到的数据包按下图的格式存于以CURR 指出的地址为首址的RAM中

当CURR=BNRY时芯片停止接收数据包

总的说来,数据包是这样被主机写入芯片和从芯片RAM读出来的:主机设置好远端DMA 开始地址(RSAR0,1)和远端DMA数据字节数(RBCR0,1),并在CR中设置读写,就可以从远端DMA口寄存器读出芯片RAM里的数据或把数据写入RAM芯片,用个示例来说明一下(以发送为例):

首先了解RBCR0,1中的远端DMA字节数在寄存器高低位上是怎么存储的?比如长度为

600字节,如下:(十进制600=十六进制258)

PG0W_RBCR0 = 600 & 0xff; //0x58

PG0W_RBCR1 = 600 >> 8; //0x2

同样道理写入地址:

PG0W_RSAR0 = XMIT_START & 0xff;

PG0W_RSAR1 = XMIT_START >> 8;

然后发送:

NIC_CR = (CR_PAGE0 | CR_DMA_WRITE | CR_START);

此时CPU通过远端DMA发送了网卡RAM中的指定区域数据

2-5网卡RAM的空间分配

网卡RAM的空间分配(包括收缓冲区、发缓冲区、数据存储区),RAM空间原则上是随意分配的,看了资料很多的分配方案都是如下:

RAM总共16k,可以用来存储数据的地址是0x4000-0x7FFF,为什么呢?看一下RAM的结构

图7 网卡RAM结构图

因为256个字节称为一页,所以0x4000-0x7FFF可以用页表示为0x40---0x7F,下面采用的也基本都是用页的地址,如:

0x4000-0x40ff是一页,我们称该页为第0x40页(或页0x40),页码也就是16位地址的高8位. 0x4100-0x41ff 是一页,称为第0x41页.

0x4000-0x7fff共16k字节的ram是网卡接收和发送数据包用的,该16k字节的ram实际上是双端口的ram,可以同时被网卡读/写和用户读/写,相互之间不影响,网卡读/写比用户读写的优先级高,

举个例子:

假如网卡收到一个数据包,需要放到0x5000开始的缓冲区,那么需要写入第0x50页.

这时用户同时读取旧的数据包,该数据包放在0x4000开始的一段缓冲区,那么需要读第0x40页.

网卡优先,它先写入一个字节,然后才读取一个字节到ISA总线上.内部总线的速度很快,是20Mhz,而ISA总线只有8Mhz, 网卡足够快进行同时读写数据,互不影响.

既然如此,我们做如下定义:0x40---0x4B共12页做为网卡的发送缓冲区,刚好可以存储两个最大的网络包(约1.5k一个最大网络包),另外使用0x4C---0x7F为网卡的接收缓冲区,共52页,如下定义:

Reg04=0x40;//参看RTL8019手册,04在寄存器页0发状态为TPSR,即发送首地址

Reg01=0x4C;//参看RTL8019手册,01在寄存器页1写状态为PSTART,即接收首地址

Reg02=0x80;//参看RTL8019手册,01在寄存器页2写状态为PSTOP,即接收尾地址

2-6关于网卡MAC地址:

0x00e0-0x00ff:52525454ABAB3D3D8E8E2C2C545446464C4C49494E4E404022222020575757 57 ,那么该网卡的地址是:5254AB3D8E2C,单地址和双地址的内容是重复的.一般使用偶数地址的内容,Prom是网卡在复位的时候从93C46里读出来的.如果你没有使用93C46,那么就不要使用Prom.,那么如何获得网卡的地址,有两种方法,一是直接读93C46,二是读Prom.

网卡在工作的时候的网卡地址是由寄存器MAR0,MAR1,MAR2,MAR3,MAR4,MAR5决定,而不是93C46,也不是Prom. 而这几个寄存器的内容需要用户自己编写程序写入,一般可以读出Prom里的网卡地址,然后写入到这6个寄存器里.如果你没有使用93C46,那么Prom也是不可以使用的,这时要由你的程序自己指定一个网卡地址, 网卡地址不能跟别的网卡地址相同,写入到MAR0-MAR5里.

例如使:

MAR0=00

MAR1=00

MAR2=00

MAR3=00

MAR4=00

MAR5=08

那么网卡的地址就是:

00:00:00:00:00:08

所有发给00:00:00:00:00:08地址的数据包就可以被网卡收到.

发送数据包的时候你的程序也要使用MAR0-MAR5的值作为发送的源地址.

2-7 关于IO端口

几乎每一种外设都是通过读写设备上的寄存器来进行的。外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU对外设IO端口物理地址的编址方式有两种:一种是I/O映射方式(I/O-mapped),另一种是内存映射方式(Memory-mapped)。而具体采用哪一种则取决于CPU的体系结构。

有些体系结构的CPU(如,PowerPC、m68k等)通常只实现一个物理地址空间(RAM)。在这种情况下,外设I/O端口的物理地址就被映射到CPU的单一物理地址空间中,而成为内存的一部分。此时,CPU可以象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。这就是所谓的“内存映射方式”(Memory-mapped)。

而另外一些体系结构的CPU(典型地如X86)则为外设专门实现了一个单独地地址空间,称为“I/O地址空间”或者“I/O端口空间”。这是一个与CPU的RAM物理地址空间不同的地址空间,所有外设的I/O端口均在这一空间中进行编址。CPU通过设立专门的I/O指令(如X86的IN和OUT指令,linux的outb,inb等,后面代码有用到)来访问这一空

间中的地址单元(也即I/O端口)。这就是所谓的“I/O映射方式”(I/O-mapped)。与RAM物理地址空间相比,I/O地址空间通常都比较小,如x86 CPU的I/O空间就只有64KB (0-0xffff)。这是“I/O映射方式”的一个主要缺点。

Linux采用内存映射方式。

我们通过上面的知识联系一下网卡的驱动:也就是说网卡的IO端口的物理地址被映射到CPU的物理地址上,即上面说的“网卡在CPU的存储空间上接BANK4,即0x08000000”

(三)、linux下网卡的驱动简介

3-1 linux下网卡驱动的基本概述

在Linux中,为了简化对设备的管理,将所有的外围设备都归结为三类:字符设备(如键盘,鼠标等)、块设备(如硬盘、软驱等)和网络设备(如网卡、串口等等)。为了将网络环境中的物理网络设备的多样性屏蔽,Linux对所有的网络物理设备抽象并且定义了一个统一的概念:接口(Interface)。对于所有的网络硬件的访问都是通过接口进行访问的,接口实际上提供了一个对于所有类型的网络硬件的一致化的操作集合,用来处理对数据的发送和接收。对于每一个已经驱动了的网络设备,都用一个struct device的数据结构表示。在内核启动或者驱动模块插入时,通过网络驱动程序,向系统注册检测到的网络设备。在进行网络数据传输的时候,网络驱动程序需要负责通过标准的接口将数据发送到相应的网络层,或者向网络发送数据包,而由以dev_base为头指针的设备链表来集体管理所有网络设备,该设备链表中的每个元素代表一个网络设备接口。数据结构device中有很多供系统访问和协议层调用的设备方法,包括供设备初始化和系统注册用的init函数,打开和关闭网络设备的open和stop 函数,处理数据包发送的hard_start_xmit函数,以及中断处理函数等

网络设备作为其中的三类设备之一,它有其非常特殊的地方。它与字符设备及块设备都有很大的不同:

(1)、网络接口不存在于Linux的文件系统中,而是在核心中用一个device数据结构表示的。每一个字符设备或块设备则在文件系统中都存在一个相应的特殊设备文件来表示该设备,如/dev/hda1、/dev/sda1、/dev/tty1等。网络设备在做数据包发送和接收时,直接通过接口访问,不需要进行文件的操作;而对字符设备和块设备的访问都需通过文件操作界面。

(2)、网络接口是在系统初始化时实时生成的,对于核心支持的但不存在的物理网络设备,将不可能有与之相对应的device结构。而对于字符设备和块设备,即使该物理设备不存在,在/dev下也必定有相应的特殊文件与之相对应。且在系统初始化时,核心将会对所有内核支持的字符设备和块设备进行登记,初始化该设备的文件操作界面(struct file_operations),而不管该设备在物理上是否存在。

以上两点是网络设备与其他设备之间存在的最主要的不同。然而,它们之间又有一些共同之处,如在系统中一个网络设备的角色和一个安装的块设备相似。一个块设备在blk_dev数组及核心其他的数据结构中登记自己,然后根据请求,通过自己的request_function函数“发送”和“接收”数据块。相似地,为了能与外面世界进行数据交流,一个网络接口也必须在一个特殊的数据结构中登记自己。

在系统内核中,存在字符设备管理表chardevs和块设备管理表blkdevs,这两张保存着指向file_operations结构的指针的设备管理表,分别用来描述各种字符驱动程序和块设备驱动程序。

类似地,在内核中也存在着一张网络接口管理表dev_base,但与前两张表不同,dev_base 是指向device结构的指针,因为网络设备是通过device数据结构来表示的。dev_base实际上是一条device结构链表的表头,在系统初始化完成以后,系统检测到的网络设备将自动地保存在这张链表中,其中每一个链表单元表示一个存在的物理网络设备。当要发送数据时,网络子系统将根据系统路由表选择相应的网络接口进行数据传输,而当接收到数据包时,通过驱动程序登记的中断服务程序进行数据的接收处理(软件网络接口除外)。以下是网络设备工作原理图:

图一Linux网络设备工作原理图

每一个具体的网络接口都应该有一个名字,以在系统中能唯一标识一个网络接口。通常一个名字仅表明该接口的类型。Linux对网络设备命名有以下约定:(其中N为一个非负整数) ethN 以太网接口,包括10Mbps和100Mbps;

trN 令牌环接口;

slN SLIP网络接口;

pppN PPP网络接口,包括同步和异步;

plipN PLIP网络接口,其中N与打印端口号相同;

tunlN IPIP压缩频道网络接口;

nrN NetROM虚拟设备接口;

isdnN ISDN网络接口;

dummyN 空设备;

lo 回送网络接口。

3-2 重要数据结构——struct device

结构device存储一个网络接口的重要信息,是网络驱动程序的核心。在逻辑上,它可以分割为两个部分:可见部分和隐藏部分。可见部分是由外部赋值;隐藏部分的域段仅面向系统内部,它们可以随时被改变。下面我们将对之进行详细的分析和解剖。

/* from include/linux/netdevice.h */

struct device

{

(1)、属性

*name;

char

设备的名字。如果第一字符为NULL(即’\0’),register_netdev (drivers/net/net_init.c)将会赋给它一个n最小的可用网络设备名eth n。

unsigned long rmem_end; /* shmem "recv" end */

unsigned long rmem_start; /* shmem "recv" start */

unsigned long mem_end; /* shared mem end */

unsigned long mem_start; /* shared mem start */

这些域段标识被设备使用的共享内存的首地址及尾地址。如果设备用来接收和发送的内存块不同,则mem域段用来标识发送的内存位置,rmem用来标识接收的内存位置。

mem_start和mem_end可在系统启动时用内核的命令行指定,用ifconfig可以查看它们的值。rmem域段从来不被驱动程序以外的程序所引用。

unsigned long base_addr; /* device I/O address */

IRQ

number */

device

unsigned

char irq;

/*

I/O基地址和中断号。它们都是在设备检测期间被赋值的,但也可以在系统启动时指定传入(如传给LILO)。ifconfig命令可显示及修改他们的当前值。

volatile unsigned char start;/* start an operation */

volatile unsigned char interrupt; /* interrupt arrived */

这是两个二值的低层状态标志。通常在设备打开时置start标志,在设备关闭时清start 标志。当interrupt置位时,表示有一个中断已到达且正在进行中断服务程序理。

unsigned long tbusy; /* transmitter busy must be long for bitops */ 标识“发送忙”。在驱动程序不能接受一个新的需传输的包时,该域段应该为非零。

struct device *next;

指向下一个网络设备,用于维护链表。

unsigned char if_port;

记录哪个硬件I/O端口正在被接口所用,如BNC,AUI,TP等(drivers/net/de4x5.h)。 unsigned char dma;

设备用的DMA通道。

一些设备可能需要以上两个域段,但非必需的。

unsigned long trans_start; /* Time (in jiffies) of last Tx */

上次传输的时间点(in jiffies)

unsigned long last_rx; /* Time of last Rx */

上次接收的时间点(in jiffies)。如trans_start可用来帮助内核检测数据传输的死锁

(lockup)。

unsigned short flags; /* interface flags (a la BSD) */

该域描述了网络设备的能力和特性。它包括以下flags:(include/linux/if.h)

IFF_UP

表示接口在运行中。当接口被激活时,内核将置该标志位。

IFF_BROADCAST

表示设备中的广播地址时有效的。以太网支持广播。

IFF_DEBUG

调试模式,表示设备调试打开。当想控制printk及其他一些基于调试目的的信息显示时,可利用这个标志位。虽然当前没有正式的驱动程序使用它,但它可以在程序中通过ioctl来设置从而使用它。

IFF_LOOPBACK

表示这是一个回送(loopback)设备,回送接口应该置该标志位。核心是通过检查此标志位来判断设备是否是回送设备的,而不是看设备的名字是否是lo。

IFF_POINTTOPOINT

表示这是一个点对点链接(SLIP and PPP),点对点接口必须置该标志位。Ifconfig 也可以置此标志位及清除它。若置上该标志位,则dev->dstaddr应也相应的置为链接对方的地址。

IFF_MASTER /* master of a load balancer */

IFF_SLA VE /* slave of a load balancer */

此两个标志位在装入平等化中要用到。

IFF_NOARP

表示不支持ARP协议。通常的网络接口能传输ARP包,如果想让接口不执行ARP,可置上该标志位。如点对点接口不需要运行ARP。

IFF_PROMISC

全局接受模式。在该模式下,设备将接受所有的包,而不关这些包是发给谁的。在缺省情况下,以太网接口会使用硬件过滤,以保证只接受广播包及发给本网络接口的包。Sniff的原理就是通过设置网络接口为全局接受模式,接受所有到达本接口媒介的包,来“偷听”本子网的“秘密”。

IFF_MULTICAST

能接收多点传送的IP包,具有多点传输的能力。ether_setup缺省是置该标志位的,故若不想支持多点传送,必须在初始化时清除该标志位。

IFF_ALLMULTI

接收所有多点传送的IP包。

IFF_NOTRAILERS /*无网络TRAILER*/

IFF_RUNNING /*资源被分配*/

此标志在Linux中没什么用,只是为了与BSD兼容。

unsigned short family; /* address family ID (AF_INET) */

该域段标识本设备支持的协议地址簇。大部分为AF_INET(英特网IP协议),接口通常不需要用这个域段或赋值给它。

unsigned short metric; /* routing metric (not used) */

unsigned short mtu;

不包括数据链路层帧首帧尾的最大传输单位(Maximum Transfer Unit)。网络层在包传输时要用到。对以太网而言,该域段为1500,不包括MAC帧的帧首和帧尾(MAC帧格式稍后所示)。

hardware

type */

short type; /*

interface

unsigned

接口的硬件类型,描述了与该网络接口绑在一起的媒介类型。Linux网络设备支持许多不同种类的媒介,如以太网,X.25,令牌环,SLIP,PPP,Apple Localtalk等。ARP 在判定接口支持哪种类型的物理地址时要用到该域段。若是以太网接口,则在ether_setup中将之设为ARPHRD_ETHER(Ethernet 10Mbps)。

unsigned short hard_header_len; /* hardware hdr length */

在被传送的包中IP头之前的字节数。对于以太网接口,该域段为14(ETH_HLEN,include\linux\if_ether.h),这个值可由MAC帧的格式得出:

MAC帧格式:

目的地址(6字节)+ 源地址(6字节)+ 数据长度(2字节)+ 数据(46~~1500)+FCS

data

*/

private

to

pointer

void *priv; /*

该指针指向私有数据,通常该数据结构中包括struct enet_statistics。类似于struct file的private_data指针,但priv指针是在设备初始化时被分配内存空间的(而不是在设备打开时),因为该指针指向的内容包括设备接口的统计数据,而这些数据即使在接口卸下(down)时也应可以得到的,如用户通过ifconfig查看。

unsigned char pad; /* make dev_addr aligned to 8 bytes */

unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */

广播地址由六个0xff构成,即表示255.255.255.255。

memset(dev->broadcast,0xFF, ETH_ALEN); (drivers/net/net_init.c)

unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */

设备的物理地址。当包传送给驱动程序传输时,要用物理地址来产生正确的帧首。

unsigned char addr_len; /* hardware address length */

物理地址的长度。以太网网卡的物理地址为6字节(ETH_ALEN)。

unsigned long pa_addr; /* protocol address */

unsigned long pa_brdaddr; /* protocol broadcast addr */

unsigned long pa_mask; /* protocol netmask */

该三个域段分别描述接口的协议地址、协议广播地址和协议的网络掩码。若dev->family 为AF_INET,则它们即为IP地址。这些域段可用ifconfig赋值。

address

protocol

length */

short pa_alen;

/*

unsigned

协议地址的长度。AF_INET的为4。

unsigned long pa_dstaddr; /* protocol P-P other side addr */

点对点协议接口(如SLIP、PPP)用这个域记录连接另一边的IP值。

struct dev_mc_list *mc_list; /* Multicast mac addresses */

int mc_count; /* Number of installed mcasts*/

struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */

这三个域段用于处理多点传输。其中mc_count表示mc_list中的项目数。

__u32 tx_queue_len; /* Max frames per queue allowed */

一个设备的传输队列能容纳的最大的帧数。对以太网,缺省为100;而plip则为节省系统资源,仅设为10。

/* For load balancing driver pair support */

unsigned long pkt_queue; /* Packets queued */

struct device *slave; /* Slave device */

struct net_alias_info *alias_info; /* main dev alias info */

struct net_alias *my_alias; /* alias devs */

struct sk_buff_head buffs[DEV_NUMBUFFS];

指向网络接口缓冲区的指针。

3-3 服务处理程序

以下是一些对网络接口的操作,类似于字符设备和块设备。网络接口操作可以分为两部分,一部分为基本操作,即每个网络接口都必须有的操作;另一部分是可选操作。

/* 基本操作 */

int (*init) (struct device *dev); /* Called only once. */

初始化函数的指针,仅被调用一次。当登记一个设备时,核心一般会让驱动程序初始化该设备。初始化函数功能包括以下内容:检测设备是否存在;自动检测该设备的I/O端口和中断号;填写该设备device结构的大部分域段;用kmalloc分配所需的内存空间等。若初始化失败,该设备的device结构就不会被链接到全局的网络设备表上。

在系统启动时,每个驱动程序都试图登记自己,当只有那些实际存在的设备才会登记成功。这与用主设备号及次设备号索引的字符设备和块设备不同。

int (*open) (struct device *dev);

打开网络接口。每当接口被ifconfig激活时,网络接口都要被打开。Open操作做以下工作:登记一些需要的系统资源,如IRQ、DMA、I/O端口等;打开硬件;将module 使用计数器加一。

int (*stop) (struct device *dev);

停止网络接口。操作内容与open相逆。

int (*hard_start_xmit) (struct sk_buff *skb, struct device *dev);

硬件开始传输。这个操作请求对一个包的传输,这个包原保存在一个socket缓冲区结构中(sk_buff)。

int (*hard_header) (struct sk_buff *skb, struct device *dev, unsigned short type,

void *daddr, void *saddr, unsigned len);

这个函数可根据先前得到的源物理地址和目的物理地址建立硬件头(hardware header)。以太网接口的缺省函数是eth_header。

int (*rebuild_header)(void *eth, struct device *dev, unsigned long raddr, struct sk_buff *skb);

在一个包被发送之前重建硬件头。对于以太网设备,若有未知的信息,缺省函数将使用ARP填写。

struct enet_statistics* (*get_stats)(struct device *dev);

当一个应用程序需要知道网络接口的一些统计数据时,可调用该函数,如ifconfig、netstat等。

/* 可选操作 */

void (*set_multicast_list)(struct device *dev);

设置多点传输的地址链表(*mc_list)。

int (*set_mac_address)(struct device *dev, void *addr);

改变硬件的物理地址。如果网络接口支持改变它的硬件物理地址,就可用这个操作。

许多硬件不支持该功能。

int (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);

执行依赖接口的ioctl命令。

int (*set_config)(struct device *dev, struct ifmap *map);

改变接口配置。设备的I/O地址和中断号可以通过该函数进行实时修改。

void (*header_cache_bind)(struct hh_cache **hhp, struct device *dev,

unsigned short htype, __u32 daddr);

void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char * haddr);

int (*change_mtu) (struct device *dev, int new_mtu);

这个函数负责使接口MTU改变后生效。如果当MTU改变时驱动程序要作一些特殊的事情,就应该写这个函数。

struct iw_statistics* (*get_wireless_stats) (struct device *dev);

};

(四)、网卡驱动程序初始化

网卡初始化是网卡驱动程序中最重要的部份,它有两种初始化模式,即“模块初始化模式”

和“起动初始化模式”

1、“模块初始化模式”的分析

(a)、概述

insmod命令将调用相应模块的init_module(),装载模块。init_module函数在初始化dev->init函数指针后,将调用register_netdev()在系统登记该设备。若登记成功,则模块装载成功,否则返回出错信息。register_netdev首先检查设备名是否已确定,若没赋值则给它一个缺省的值ethN,N为最小的可用以太网设备号注;然后,网络设备自己的init_function,即刚在init_module中赋值的dev->init,将被调用,用来实现对网络接口的实际的初始化工作。若初始化成功,则将该网络接口加到网络设备管理表dev_base的尾部。整个函数调用关系图如下所示。下面我们以用得最广泛以太网卡之一——NE2000兼容网卡为例子进行分析。NE2000网卡的主要驱动程序在文件drivers/net/ne.c中。

图二“模块初始化模式”的函数调用关系图

(b)、init_module

init_module---模块初始化函数,当装载模块时,核心将自动调用该函数。在此函数中一般处理以下内容:

1.处理用户可能传入的参数name、ports及irq的值。若有,则赋给相应的接口(注意:未登记);

2.对dev->init函数指针进行赋值,对于任何网络设备这一步必不可少!!因为在register_netdev中要用到该函数指针;

3.调用register_netdev,完成检测、初始化及设备登记等工作。

/* from drivers/net/ne.c */

init_module(void)

{

int this_dev, found = 0;

/* 对所有可能存在的以太网接口进行检测并试图去登记,MAX_NE_CARDS为4, * 即最多可以使用4块NE2000兼容网卡。 */

for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {

struct device *dev = &dev_ne[this_dev];

/* 可能有用户传入的参数:指定的name、ports及irq的值 */

dev->name = namelist+(NAMELEN*this_dev);

dev->irq = irq[this_dev];

dev->base_addr = io[this_dev];

ne_probe; /*

NE2000的检测和初始化函数 */

=

dev->init

dev->mem_end = bad[this_dev];

if (register_netdev(dev) == 0) { /* 试图登记该设备 */

found++;

continue; /* 设备登记成功,继续登记下一个设备 */ }

/* 第一次发生登记不成功事件 */

if (found != 0) /* 在这之前没有成功登记NE2000接口,返回 */

0;

return

/* 显示出错信息 */

if (io[this_dev] != 0)

printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);

else

printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for …………

(c)、register_netdev

该函数实现对网络接口的登记功能。其实现步骤如下:

1.首先检查设备名是否已确定,若没赋值则以以太网设备待之并给它一个缺省的值ethN,N为最小的可用以太网设备号;

2.然后,网络设备自己的init_function,即刚在init_module中赋值的dev->init,将被调用,用来实现对网络接口的实际的初始化工作。

3.若初始化成功,则将该网络接口加到网络设备管理表dev_base的尾部

/* from drivers/net/net_init.c */

int register_netdev(struct device *dev)

{

struct device *d = dev_base; /* 取得网络设备管理表的表头指针 */

…………

if (dev && dev->init) {

/*若设备名字没确定,则将之看作是以太网设备!!*/

if (dev->name &&

((dev->name[0] == '\0') || (dev->name[0] == ' '))) {

/* 找到下一个最小的空闲可用以太网设备名字 */

for (i = 0; i < MAX_ETH_CARDS; ++i)

if (ethdev_index[i] == NULL) {

i);

sprintf(dev->name,

"eth%d",

device '%s'...\n", dev->name);

printk("loading

dev;

=

ethdev_index[i]

break;

}

}

…………

/* 调用初始化函数进行设备的初始化 */

if (dev->init(dev) != 0) {

…………

/* 将设备加到网络设备管理表中,加在最后 */

if (dev_base) {

/* 找到链表尾部 */

(d->next)

while

=

d->next;

d

=

dev;

d->next

}

else

dev;

dev_base

=

dev->next = NULL;

…………

(d)、init_function

函数原型:int init_function (struct device *dev);

当系统登记一个网络设备时,核心一般会请求该设备的驱动程序初始化自己。初始化函数功能包括以下内容:

1.检测设备是否存在,一般和第二步一起作;

2.自动检测该设备的I/O地址和中断号;

对于可以与其他共享中断号的设备,我们应尽量避免在初始化函数中登记I/O地

址和中断号,I/O地址和中断号的登记最好在设备被打开的时候,因为中断号有可

能被其他设备所共享。若不准备和其他设备共享,则可在此调用request_irq和

request_region马上向系统登记。

3.填写传入的该设备device结构的大部分域段;

对于以太网接口,device结构中许多有关网络接口信息都是通过调用ether_setup

函数(driver/net/net_init.c)统一来设置的,因为以太网卡有很好的共性。对于非以

太网接口,也有一些类似于ether_setup的函数,如tr_setup(令牌网),fddi_setup。

若添加的网络设备都不属于这些类型,就需要自己填写device结构的各个分量。

4.kmalloc需要的内存空间。

若初始化失败,该设备的device结构就不会被链接到全局的网络设备表上。在系统启动时,每个驱动程序都试图登记自己,当只有那些实际存在的设备才会登记成功。这与用主设备号及次设备号索引的字符设备和块设备不同。

物理设备NE2000兼容网卡的初始化函数是由ne_probe和ne_probe1及ethdev_init共同实现。

/* from drivers/net/ne.c */

int ne_probe(struct device *dev)

{

…………

int base_addr = dev ? dev->base_addr : 0;

/* I/O地址. User knows best. */

if (base_addr > 0x1ff) /* I/O地址有指定值 */

return ne_probe1(dev, base_addr); /* 这个函数在下面分析 */

else if (base_addr != 0) /* 不自动检测I/O */

return ENXIO;

…………

/* base_addr=0,自动检测,若有第二块ISA网卡则是一个冒险!?* 对所有NE2000可能的I/O地址都进行检测,可能的I/O地址在存在

* netcard_portlist数组中:

* static unsigned int netcard_portlist[]={ 0x300, 0x280, 0x320, 0x340, 0x360, 0};

*/

for (i = 0; netcard_portlist[i]; i++) {

int ioaddr = netcard_portlist[i];

if (check_region(ioaddr, NE_IO_EXTENT))

continue;

/* 检测到一个I/O端口地址 */

if (ne_probe1(dev, ioaddr) == 0)

return 0;

…………

/* from drivers/net/ne.c */

static int ne_probe1(struct device *dev, int ioaddr)

{

…………

/* 检测、确认I/O地址;初始化8390 */

…………

/* 自动检测中断号,非常巧妙!! */

if (dev->irq < 2) {

autoirq_setup(0); /* 自动检测准备 */

outb_p(0x50, ioaddr + EN0_IMR); /* 中断使能 */

outb_p(0x00, ioaddr + EN0_RCNTLO);

outb_p(0x00, ioaddr + EN0_RCNTHI);

outb_p(E8390_RREAD+E8390_START, ioaddr); /* 触发中断 */

outb_p(0x00, ioaddr + EN0_IMR); /* 屏蔽中断 */

dev->irq = autoirq_report(0); /* 获得刚才产生的中断号 */ …………

…………

/* 登记中断号,中断服务程序为ei_interrupt。

* 因为ISA网卡不能和其他设备共享中断。*/

int irqval = request_irq(dev->irq, ei_interrupt,

pci_irq_line ? SA_SHIRQ : 0, name, dev);

if (irqval) {

printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);

return EAGAIN;

}

dev->base_addr = ioaddr; /* 设置I/O地址——已经过确认 */

/* 调用ethdev_init初始化dev结构 */

if (ethdev_init(dev)) { /* 该函数下面将分析 */

printk (" unable to get memory for dev->priv.\n");

free_irq(dev->irq, NULL); /* 初始化不成功,释放登记的中断号! */

return -ENOMEM;

}

/* 向系统登记I/O地址 */

request_region(ioaddr, NE_IO_EXTENT, name);

/* 将硬件的物理地址赋给dev->dev_add */

for(i = 0; i < ETHER_ADDR_LEN; i++) {

printk(" %2.2x", SA_prom[i]);

dev->dev_addr[i] = SA_prom[i];

}

printk("\n%s: %s found at %#x, using IRQ %d.\n",

dev->name, name, ioaddr, dev->irq);

…………

/* 向dev结构登记设备打开和关闭函数 */

dev->open = &ne_open;

dev->stop = &ne_close;

…………

/* from drivers/net/8390.c */

int ethdev_init(struct device *dev)

{

…………

if (dev->priv == NULL) {

struct ei_device *ei_local;

/* 申请私有数据结构空间,用于记录设备的状态等 */

dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL);

…………

dev->hard_start_xmit = &ei_start_xmit;

dev->get_stats = get_stats;

dev->set_multicast_list = &set_multicast_list;

ether_setup(dev);

…………

(e)、ether_setup

ether_setup是一个通用于以太网接口的网络接口设置函数。由于以太网卡有很好的共性,device结构中许多有关的网络接口信息都是通过调用ether_setup函数统一来设置。那么让我们看看它到底会缺省设哪些域段及设为什么值。若你满意这些缺省设置,那么在写驱动程序时只要调用一下这个函数就可以将这些域段的设置工作“置之不理了”?,否则,也可在调用该函数之后再改过。

/* from drivers/net/net_init.c */

void ether_setup(struct device *dev)

{

int i;

/* 初始化缓冲队列链表,这是一个双向链表 */

for (i = 0; i < DEV_NUMBUFFS; i++) /* DEV_NUMBUFFS=3 */ skb_queue_head_init(&dev->buffs[i]);

…………

/* 一些处理函数的初始化,驱动程序可以不写这些函数了 */ dev->change_mtu= eth_change_mtu;

dev->hard_header= eth_header;

dev->rebuild_header = eth_rebuild_header;

dev->set_mac_address = eth_mac_addr;

dev->header_cache_bind = eth_header_cache_bind;

dev->header_cache_update= eth_header_cache_update;

dev->type = ARPHRD_ETHER; /* Ethernet 10Mbps */ dev->hard_header_len= ETH_HLEN; /* MAC层协议头的大小 14 */

最大传输单位 */

1500;

/*

dev->mtu

=

dev->addr_len = ETH_ALEN; /* 协议地址长度 4 */

dev->tx_queue_len = 100; /* 传输队列的长度 */

memset(dev->broadcast,0xFF, ETH_ALEN);/* 物理地址长度 6 */

/* 广播地址有效及支持多点传输 */ dev->flags = IFF_BROADCAST|IFF_MULTICAST;

dev->family = AF_INET; /* 英特网IP协议簇 */

dev->pa_addr = 0; /* 以后用ifconfig命令设置 */

dev->pa_brdaddr= 0; /* 以后用ifconfig命令设置 */

dev->pa_mask = 0; /* 以后用ifconfig命令设置 */

dev->pa_alen = 4; /* 协议地址长度 4 */

}

至此模块化网络设备的初始化就完成了。

2、“启动初始化模式”的分析

(a)、初始化策略

“启动初始化模式”与“模块初始

化模式”不同,前者要对所有内核支

持的网络设备进行检测和初始化,而

后者仅需检测和初始化被装载模块的

网络设备。为了实现在启动时对所有

可能存在的设备进行初始化,系统在

启动之前将所有内核支持的网络设备

的名字及相应的初始化函数都挂在网

络设备管理表(dev_base)上。启动后,

net_dev_int()将依次对网络设备管理

表dev_base中的每个设备,调用该设

备本身的init_function进行初始化。若

init_function失败,即该设备不存在或I/O、IRQ不能获得,则将该设备从dev_base 去掉。这样,最后网络设备管理表中剩下的网络接口都是存在的,显然也已是被初始化过的。我们看一下dev_base的初始化情况。

/* 网络设备管理表的初始化 */

/* from drivers/net/Space.c */

…………

static struct device eth7_dev = {

"eth7", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };

static struct device eth6_dev = {

"eth6", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, ð7_dev, ethif_probe };

…………

static struct device eth0_dev = {

"eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, ð1_dev, ethif_probe };

/* 在八个eth接口中,只有eth0将I/O设为0,让其进行自动检测,其他* eth接口的I/O都设为0xffe0,不进行检测。Linux缺省的内核在启动时

* 只能自动检测到一块eth网卡,就是这个原因 */

# undef NEXT_DEV

# define NEXT_DEV (ð0_dev)

#if defined(PLIP) || defined(CONFIG_PLIP)

extern int plip_init(struct device *);

static struct device plip2_dev = {

"plip2", 0, 0, 0, 0, 0x278, 2, 0, 0, 0, NEXT_DEV, plip_init, };

…………

static struct device plip0_dev = {

"plip0", 0, 0, 0, 0, 0x3BC, 5, 0, 0, 0, &plip1_dev, plip_init, };

…………

extern int loopback_init(struct device *dev);

struct device loopback_dev = {

"lo", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, loopback_init };

struct device dev_base = &loopback_dev; /* 关键的一个语句 */

(b)、函数调用关系

系统转入核心后,start_kernel将会创建一个init进程,该init进程则会通过系统调用sys_steup进行所有尚未初始化的设备(有一些设备如内存、PCI等系统已先于此进行了初始化)。device_setup不仅要初始化内核支持的字符设备、块设备,也调用net_dev_init初始化所有内核支持的且实际存在的网络设备。net_dev_init会对每个内核支持的网络设备调用该设备的init_functions进行具体的物理设备的初始化工作。整个函数调用关系图如下:

linux网卡驱动的配置

RedHat5.1下安装Realtek8168网卡驱动 1.先识别机器上的网卡型号: [root@localhost kernel]#kudzu --probe --class=network 2、使用命令查看kernel包是否都装全了,具体如下: [root@localhost kernel]# rpm -qa | grep kernel 如果装全了,会显示如下几个包: kernel-xen-devel-2.6.18-8.el5 kernel-devel-2.6.18-8.el5 kernel-2.6.18-8.el5 kernel-xen-2.6.18-8.el5 kernel-headers-2.6.18-8.el5 如果没有装全,就在redhat enterprise Linux 5.0第一个ISO的Server文件目录下可以找到对应的包,拷贝到某一具体目录下,进入目录后,用如下命令就可以进行安装: [root@localhost kernel]# rpm -ivh kernel-devel-2.6.18-8.el5.x86_64.rpm

注意:如果不装全这些包,在网卡编译时就会报错说找不到src目录文件。 用如下命令查看GCC是否安装,通常都装上的,还是检查一下比较好。 [root@localhost 2.6.18-8.el5]# whereis -b gcc gcc : /usr/bin/gcc /usr/lib/gcc /usr/libexec/gcc 3、将r8168-8.aaa.bb.tar.bz2解压出来变成r8168-8.aaa.bb文件夹形式,拷到U盘 在redhat下挂载U盘: 插入U盘 [root@localhost kernel]#mount /dev/sdb1 /mnt/usb 4.将r8168-8.aaa.bb文件夹拷都本地,如/home目录下 首先将u盘中的驱动程序包拷贝到/home目录下 [root@localhost media]# cp r8168-8\[1\].011.00.tar.bz2 /home/ [root@localhost media]# cd /home/ [root@localhost home]# ls r8168-8[1].011.00.tar.bz2 5.其次解压驱动程序包 [root@localhost home]# tar -vjxf r8168-8\[1\].011.00.tar.bz2

linux下安装编译网卡驱动的方法

linux下安装编译网卡驱动的方法 你还在为不知道linux下安装编译网卡驱动的方法而不知所措么?下面来是小编为大家收集的linux下安装编译网卡驱动的方法,欢迎大家阅读: linux下安装编译网卡驱动的方法 安装linux操作系统后发现没有网卡驱动,表现为 system → Administration → Network下Hardware列表为空。 以下为安装编译网卡驱动的过程,本人是菜鸟,以下是我从网上找的资料进行整理,并实际操作的过程,仅供借鉴。 一.检测linux系统内核版本和网卡类型,相关命令如下: uname -r 查看linux内核版本(uname -a 可显示所有信息)

lsmod 设备加载情况 ls /usr/share/hwdata 查看硬件设备 lspci 查看pci网卡设备ethernet controller 厂商和型号,modprobe **** ****为网卡型号,例如modprobe RTL8101E ,如果出错,说明模块不存在,该型号不识别 我在这一步时查找不到网卡型号,无奈只能由同时采购的其他相同型号预装win7的电脑下查看网卡型号,是个笨办法,嘿嘿…… 找到网卡型号后就到驱动之家下载了相应网卡的linux驱动,这些需要根据自己的实际情况下载,不多说了,重点是后面。 二.下载网卡驱动 Intel_e1000e-1.9.5.zip 为我下载的所需的网卡驱动,这个在linux下需自己编译. 三.安装网卡驱动

1.检测编译需要用到内核的源代码包和编译程序gcc。所以如果没有的话,要先装。 [root@localhost ~]# rpm -qa|grep kernel kernel-xen-2.6.18-8.el5 kernel-xen-devel-2.6.18-8.el5 kernel-headers-2.6.18-8.el5 [root@localhost ~]# rpm -qa|grep gcc gcc-c++-4.1.1-52.el5 libgcc-4.1.1-52.el5 gcc-4.1.1-52.el5 gcc-gfortran-4.1.1-52.el5 如果缺少kernel-xen-devel-2.6.18-8.el5,可以去安装光

在linux系统下如何安装网卡驱动

2011年研发二部工作 周报月报 作者:赵玉武 时间:2012-6-13

目录 一、整理漏扫系统的结构 (1) 1、整理NetScan目录中的程序。 (1) 2、整理proftpd目录中内容(插件的检测信息)。 (4) 3、整理proxyd目录中的安管(安管平台)。 (8) 二、熟悉Nessus的工作原理 (8) 1、Nessus扫描引擎的工作原理... 错误!未定义书签。 三、整理运行的整个流程.............. 错误!未定义书签。 1、通过客户端下发策略,上传到服务器上。错误!未定 义书签。 2、服务端:接收客户端下发的策略。错误!未定义书签。 3、服务端进行身份的认证....... 错误!未定义书签。

一、整理漏扫系统的结构 网卡是Linux服务器中最重要网络设备。据统计,Linux网络故障有35%在物理层、25%在数据链路层、10%在网络层、10%在传输层、10%在对话、7%在表示层、3%在应用层。由此可以看出,网络故障通常发生在网络七层模型的下三层,即物理层、链路层和网络层。对应于实际网络也就是使用的网络线缆、网卡、交换机、路由器等设备故障。Linux的网络实现是模仿FreeBSD的,它支持FreeBSD 的带有扩展的Sockets(套接字)和TCP/IP协议。它支持两个主机间的网络连接和Sockets通讯模型,实现了两种类型的Sockets:BSD Sockets和INET Sockets。它为不同的通信模型和服务质量提供了两种传输协议,即不可靠的、基于消息的UDP传输协议和可靠的、基于流的传输协议TCP,并且都是在IP网络协议上实现的。INET sockets 是在以上两个协议及IP协议之上实现的。 由于交换机、路由器通常独立于Linux或者其他操作系统。网卡设置故障是造成Linux 服务器故障最主要原因。可能因为硬件的质量或性能、磨损老化、人为误操作、不正确的网络设置、管理问题、Linux软件的BUG、系统受到黑客攻击和Linux病毒等原因造成。 Linux 服务器网卡故障排除的思路是:应当遵循先硬件后软件的方法。因为硬件如果出现物理损坏那么如何设定网卡都不能解决故障。解决问题的方法可以从自身Linux计算机的网卡查起,如果确定硬件没有问题了,再来考虑软件的设定。 1、网卡的选择 一般来说,2.4版本以后的 Linux可以支持的网卡芯片组数量已经很完备了,包括著名厂商如:Intel 以及使用广泛的 RealTek, Via 等网卡芯片都已经被支持,所以使用者可以很轻易的设定好他们的网

linux驱动程序的编写

linux驱动程序的编写 一、实验目的 1.掌握linux驱动程序的编写方法 2.掌握驱动程序动态模块的调试方法 3.掌握驱动程序填加到内核的方法 二、实验内容 1. 学习linux驱动程序的编写流程 2. 学习驱动程序动态模块的调试方法 3. 学习驱动程序填加到内核的流程 三、实验设备 PentiumII以上的PC机,LINUX操作系统,EL-ARM860实验箱 四、linux的驱动程序的编写 嵌入式应用对成本和实时性比较敏感,而对linux的应用主要体现在对硬件的驱动程序的编写和上层应用程序的开发上。 嵌入式linux驱动程序的基本结构和标准Linux的结构基本一致,也支持模块化模式,所以,大部分驱动程序编成模块化形式,而且,要求可以在不同的体系结构上安装。linux是可以支持模块化模式的,但由于嵌入式应用是针对具体的应用,所以,一般不采用该模式,而是把驱动程序直接编译进内核之中。但是这种模式是调试驱动模块的极佳方法。 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。同时,设备驱动程序是内核的一部分,它完成以下的功能:对设备初始化和释放;把数据从内核传送到硬件和从硬件读取数据;读取应用程序传送给设备文件的数据和回送应用程序请求的数据;检测和处理设备出现的错误。在linux操作系统下有字符设备和块设备,网络设备三类主要的设备文件类型。 字符设备和块设备的主要区别是:在对字符设备发出读写请求时,实际的硬件I/O一般就紧接着发生了;块设备利用一块系统内存作为缓冲区,当用户进程对设备请求满足用户要求时,就返回请求的数据。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 1 字符设备驱动结构 Linux字符设备驱动的关键数据结构是cdev和file_operations结构体。

Linux下网卡驱动程序

Linux下8019网卡驱动程序 福建鑫诺通信有限公司陈光平(chenggp_fj@https://www.360docs.net/doc/246579061.html,) 本文以S3C44B0的CPU为例,详细解析了linux下RTL8019网卡驱动程序工作原理,其间知识大多来源互联网络,特别是浙大潘纲的论文,在此不一一列出,此文目的只是让嵌入式linux爱好者得到更多网卡驱动的资料,并获得交流机会,不足之处请指正 (一)、硬件相关部份 1、CPU与网卡的连接方式 (s3c44B0 CPU) (RTL 8019网卡) CPU与网卡接线图 上图为S3c44b0CPU和网卡的接线图,此接法并非固定,如接法不同,则牵涉到很多相应的改动,下面会详细分析不同之处 从硬件部门得到:网卡在CPU的存储空间上接BANK4,即0x08000000(看44B0手册)外部中断号为:EXTINT3 (irqs.h文件获得值为22) 上面两个值可以查CPU手册,或询问硬件设计人员 由上图可以知道以下数据: (1)、网卡与CPU地址线连接错开8位(A0接A8) (2)、总共连线,其实4根就足够用了,因为每根线可以译码4个地址空间,总共是16个地址空间,每个地址空间对应一个寄存器地址,而8019总共就是16个寄存器(3)、一般是跳线模式,不使用9346芯片 1-1 基地址算法 首先8019的基地址是300H(见RTL8019芯片资料:选择IO总线地址),但是有些硬件已在芯片中做过了偏移,比如我们的网卡已做了处理,基址已偏移到0x08000000, 那么因为网卡A0接CPU的A8,表示基地址左移8位,下一个寄存器reg0的地址就是:0x08000100(0000,0000,0001 0001,0000,0000) 还不理解的话我们看另一种接法:

Linux下查看网卡驱动和版本信息

Linux下查看网卡驱动和版本信息 查看网卡生产厂商和信号 查看基本信息:lspci 查看详细信息:lspci -vvv # 3个小写的v 查看网卡信息:lspci | grep Ethernet 查看网卡驱动 查看网卡驱动信息:lspci -vvv # 找到网卡设备的详细信息,包括网卡驱动 # lsmod 列出加载的所有驱动,包括网卡驱动 查看网卡驱动版本 查看模块信息:modifo # 其中包含version信息 或# ethtool-i RHEL 6.3中的网卡驱动版本: # modinfo igb filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/igb/igb.ko version: 3.2.10-k license: GPL description: Intel(R) Gigabit Ethernet Network Driver # modinfo e1000e filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/e1000e/e1000e.ko version: 1.9.5-k license: GPL

description: Intel(R) PRO/1000 Network Driver author: Intel Corporation, # modinfo e1000 filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/e1000/e1000.ko version: 8.0.35-NAPI license: GPL description: Intel(R) PRO/1000 Network Driver # modinfo ixgbe filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/ixgbe/ixgbe.ko version: 3.6.7-k license: GPL description: Intel(R) 10 Gigabit PCI Express NetworkDriver # modinfo r8169 filename: /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/net/r8169.ko version: 2.3LK-NAPI license: GPL description: RealTek RTL-8169 Gigabit Ethernet driver 查看网络接口队列数 查看网卡接口的中断信息:#cat /proc/interrupts | grep eth0 或# ethtool-S eth0 查看网卡驱动源码的版本号 解压Intel网卡驱动源码,打开解压缩目录下的*.spec文件查看驱动的版本。 例如:解压e1000-8.0.35.tar.gz网卡驱动后,查看e1000.spec文件。

Linux驱动框架及驱动加载

本讲主要概述Linux设备驱动框架、驱动程序的配置文件及常用的加载驱动程序的方法;并且介绍Red Hat Linux安装程序是如何加载驱动的,通过了解这个过程,我们可以自己将驱动程序放到引导盘中;安装完系统后,使用kudzu自动配置硬件程序。 Linux设备驱动概述 1. 内核和驱动模块 操作系统是通过各种驱动程序来驾驭硬件设备,它为用户屏蔽了各种各样的设备,驱动硬件是操作系统最基本的功能,并且提供统一的操作方式。正如我们查看屏幕上的文档时,不用去管到底使用nVIDIA芯片,还是ATI芯片的显示卡,只需知道输入命令后,需要的文字就显示在屏幕上。硬件驱动程序是操作系统最基本的组成部分,在Linux内核源程序中也占有较高的比例。 Linux内核中采用可加载的模块化设计(LKMs ,Loadable Kernel Modules),一般情况下编译的Linux内核是支持可插入式模块的,也就是将最基本的核心代码编译在内核中,其它的代码可以选择是在内核中,或者编译为内核的模块文件。 如果需要某种功能,比如需要访问一个NTFS分区,就加载相应的NTFS模块。这种设计可以使内核文件不至于太大,但是又可以支持很多的功能,必要时动态地加载。这是一种跟微内核设计不太一样,但却是切实可行的内核设计方案。 我们常见的驱动程序就是作为内核模块动态加载的,比如声卡驱动和网卡驱动等,而Linux最基础的驱动,如CPU、PCI总线、TCP/IP协议、APM(高级电源管理)、VFS等驱动程序则编译在内核文件中。有时也把内核模块就叫做驱动程序,只不过驱动的内容不一定是硬件罢了,比如ext3文件系统的驱动。 理解这一点很重要。因此,加载驱动时就是加载内核模块。下面来看一下有关模块的命令,在加载驱动程序要用到它们:lsmod、modprob、insmod、rmmod、modinfo。 lsmod

linux下安装无线网卡驱动

换了linux系统后发现无线不能使用,很是苦恼,于是在网上找到各位大神的做法,终于成功安装。下面给大家介绍一下。本例以安装Fedora 14无线网卡驱动为例。参考文章 https://www.360docs.net/doc/246579061.html,/Linux/2011-05/35366.htm。 首先在https://www.360docs.net/doc/246579061.html,/support/802.11/linux_sta.php 上下载32位的驱动, 下载完成之后进入到下载的文件夹下 #cd ~/Downloads 按照readme的做法,新建一个文件夹,并且将该压缩文件移动到新建的文件夹当中 #mkdri hybrid_wl #mv hybrid-portsrc-x86_32-v5.60.48.36.tar.gz hybrid_wl/ 进入文件夹,进行解压, #cd hybrid_wl/ #tar -zxvf hybrid-portsrc-x86_32-v5.60.48.36.tar.gz 由于自述文件当中的做法是指定解压目录,因此为了保险,再把这个压缩文件移动到上一级目录 #mv hybrid-portsrc-x86_32-v5.60.48.36.tar.gz ../ 根据自述文件的说法(The cards with the following PCI Device IDs are supported with this driver.),查看支持的版本 # lspci -n | grep 14e4 0c:00.0 0280: 14e4:4315 (rev 01) BRCM PCI PCI DellProduct Name Vendor ID Device ID Product ID ------------- ---------- --------- ----------- 4311 2.4 Ghz 0x14e4 0x4311 Dell 1390 4311 Dualband 0x14e4 0x4312 Dell 1490

Linux网卡驱动程序详解

当网络上一台计算机准备发送数据时,他的网卡开始工作了,首先网卡的芯片侦听在网络上是否有数据在流动,如果没有,他就把数据发送到网络上,在侦听和发送之间有一段极小的时间延迟,在这段时间内,也有可能在网络上有其他的计算机也准备发送数据,也侦听到网络上没有数据在流动,这就可能两台甚至多台的数据一起发送到网络上,产生数据的碰撞,发送数据的计算机的网卡芯片当然要在发送完成后再校验返回的数据,如果发现和发送的数据不一致,那就是说产生了碰撞,所以在一个以太网络中的计算机数量不宜过多,他不但会增加广播包在网络中的数量,也请也会增加数据包的碰撞次数. 我们的计算机的网卡芯片在接收到一完整的数据包后,芯片的一引脚通知8259中断控制器,中断控制器再发出中断给CPU,由此,CPU随即调用该网卡的中断例程,如: DOS是这样的 屏蔽所有中断(cli) push any register 因为中断向量在段0 所以xor ax,ax mov ds,ax mul ax,中断号 那么在数据段的[ax]偏移处是该中断例程的指针了call [ax]就到该中断例程了...(DOS是比较遥远的事情了,我所描述的是他的原理,当然不会这么简单,如果那位网友有兴趣详细描述一下上面的原理,纠正或替换掉我所写的就感激不尽了) 总之,在本例程中,CPU将调用elintr中断例程,并带有参数unit即该种网卡的第几块(因为在计算机中,你有可能装了相同的网卡有几块),elintr的作用是把数据从网卡的数据存储器中读到我们在该网卡初始化时预先分配好的数据缓冲区中,他调用的函数就只有elread,同样elread也只调用了elget一个函数.elread函数比较简单,就是调用elget,elget则相对比较复杂一点,涉及到核心内存分配mbuf,mbuf是比较恐怖的东西,正如STEVEN所写的,为了节约当时"巨大"的4M内存,牺牲了性能搞出了这个mbuf东东,mbuf是必须要弄懂的,虽然在设备驱动程序中调用他的宏和函数不多,但在后面的IP协议,TCP协议中有不少涉及的地方. 关于数据发送方面和接收差不多,在上层协议放置好数据到mbuf链后,调用el_start函数,该函数把mbuf链中的数据放置到本块网卡的发送队列缓冲el_pktbuf中,然后再调用el_xmit 函数,此函数把发送队列缓冲el_pktbuf中的数据有传递到网卡的数据存储器中.我认为,这中间的内存拷贝是多于的,应该在el_start函数中直接把mbuf中的数据传递到网卡的数据存储器中,这样会使性能有较大幅度的提升,因为在驱动程序设计时,最好减少大量的内存拷贝,他占用的时间太多了. */ /* FreeBSD的3COM以太网设备驱动程序*/ /*本段头文件是在编译核心时产生的*/ #include "el.h" /*此三文件为编译时产生的头文件,内容是定制核心的一些常量*/ #include "opt_inet.h"

基于Linux系统的HHARM9电机驱动程序设计

收稿日期:2005-09-22 作者简介:朱华生(1965-),男,江西临川人,副教授. 文章编号:1006-4869(2005)04-0051-03 基于Linux 系统的HHARM9电机驱动程序设计 朱华生,胡凯利 (南昌工程学院计算机科学与技术系,江西南昌330099) 摘 要:对嵌入式Linux 操作系统驱动程序的组成进行分析,讨论了驱动程序的基本框架,以HHARM9电机控制为实例,详细论述了电机驱动程序的实现过程. 关键词:嵌入式;Linux;驱动程序 中图分类号:TP316 文献标识码:A Linux System -Based Design of HHARM 9Electromotor Driver ZHU Hua -sheng,HU Ka-i li (Department of Computer and Science,Nanchang Institute of Technology,Nanchang 330099,China) Abstract:The paper analyses the composition of driver in embedded linux system,disuses its basic frame of driver,and illustrales the process of driver design of HHARM9electromotor in detail. Key words:Embedded;Linux; driver 嵌入式Linux 操作系统因具有免费、开放源代码、强大的网络功能等 特点,在嵌入式产品中得到越来越广泛的应用.基于Linux 操作系统的嵌入 式产品结构[1]如图1所示.本文主要探讨嵌入式系统驱动程序的设计. 1 嵌入式Linux 操作系统驱动程序简介 1)驱动程序和应用程序的区别 驱动程序的设计和应用程序的设计有很大的区别[2].首先,驱动程序 的设计要对硬件的结构、信号的工作流程十分清楚,而在应用程序的设计 中,一般不需要了解这些.其次,应用程序一般有一个main 函数,从头到尾 执行一个任务;驱动程序却不同,它没有main 函数,通过使用宏module _init(初始化函数名),将初始化函数加入内核全局初始化函数列表中,在内核初始化时执行驱动的初始化函数,从而完成驱动的初始化和注册,之后驱动便停止等待被应用软件调用.应用程序可以和GLIB C 库连接,因此可以包含标准的头文件,比如等;在驱动程序中,不能使用标准C 库,因此不能调用所有的C 库函数,比如输出打印函数只能使用内核的printk 函数,包含的头文件只能是内核的头文件,比如. 2)Linux 系统设备文件 为了方便应用程序的开发,在Linux 操作系统中,使用了设备文件这一概念来管理硬件设备.Linux 操 第24卷 第4期 2005年12月南昌工程学院学报Journal of Nanchang Institute of Technology Vol.24No.4Dec.2005

LINUX下安装无线网卡驱动程序

1.1下载驱动程序 一、首先弄清楚当前使用的是什么版本的Linux,如:Redhat9.0、Freda core5等。Linux用的是什么版本的内核,可以用uname –a得知内核版本号。 二、使用的是什么接口类型的无线网卡,常见的接口类型有PCI (台式机)、Cardbus/PCMCIA(笔记本)、USB(台式机、笔 记本)等。 三、无线网卡使用的是哪一种类型的芯片,判断方法如下,到相 关网站下载与其相对应的驱动程序。常用的无线网卡驱动及其支 持的芯片类型和接口类型如下表1所示。 PCMCIA卡:将无线网卡插入笔记本电脑中,用命令lspci可以看到芯片类型,如: Realtek Semiconductor Co.. Ltd, RTL8180L802.11b MAC (rev 20)

其中RTL8180L即为网卡芯片类型,用参数v可以看到更详细的信 息。 USB卡:用命令lsusb可以看到芯片类型(fc5没有此命令)。通过其它方法查找。 驱动程序芯片类型接口类型官方网站下载页 Linux-wlan-ng Prism2/2.5/3 Cardbus/PCI/USB https://www.360docs.net/doc/246579061.html,/download.shtml Madwifi Atheros系列Cardbus/PCI https://www.360docs.net/doc/246579061.html,/ islsm ISL38XX USB/PCI http://jbnote.free.fr/prism54usb/index.html 表1:网卡驱动程序有关信息 1.2驱动程序的安装 每款驱动的安装方法各不相同,阅读INSTALL文档,获得驱动程 序的具体安装方法及系统内核要求。阅读驱动程序附带的 README文档,获得有关此驱动的详细信息,如驱动所支持的网 络模式、接口类型、所包含的模块的功能及无线网卡的配置等。 下面是安装网卡驱动程序的一般步骤: 编译网卡驱动程序 #make

linux驱动程序进入内核

ARM-uClinux下编写加载驱动程序详细过程 本文主要介绍在uClinux下,通过加载模块的方式调试IO控制蜂鸣器的驱动程序。实验过程与上篇文章所讲的过程基本相似,更多注重细节及注意事项。 本文适合学习ARM—Linux的初学者。 //================================================================== 硬件平台:MagicARM2200教学试验开发平台(LPC2290) Linux version 2.4.24,gcc version 2.95.3 电路连接:P0.7——蜂鸣器,低电平发声。 实验条件:uClinux内核已经下载到开发板上,能够正常运行;与宿主机相连的网络、串口连接正常。 //================================================================== 编写蜂鸣器的驱动程序相对来说容易实现,不需要处理中断等繁琐的过程,本文以蜂鸣器的驱动程序为例,详细说明模块化驱动程序设计的主要过程和注意事项。 一、编写驱动程序 驱动程序的编写与上文所说的编写过程基本相同,这里再详细说明一下。 //========================================== //蜂鸣器驱动程序:beep.c文件 //------------------------------------------------------------------- #include /*模块相关*/ #include /*内核相关*/ #include /*linux定义类型*/ #include /*文件系统 file_opertions 结构体定义*/ #include /*出错信息*/ /*PINSEL0 注意:低2位是UART0复用口,不要改动*/ #define PINSEL0 (*((volatile unsigned*) 0xE002C000)) /*P0口控制寄存器*/ #define IO0PIN (*((volatile unsigned*) 0xE0028000))

linux查看网卡型号、驱动版本、队列数

一、如何查看网卡生产厂家和型号? lspci命令 查看基本信息 lspci,详细信息lspci -vvv 00:00.0 Host bridge: Intel Corporation 5520 I/O Hub to ESI Port (rev 13) 00:01.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 1 (rev 13) 00:02.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 2 (rev 13) 00:03.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 3 (rev 13) 00:04.0 PCI bridge: Intel Corporation 5520/X58 I/O Hub PCI Express Root Port 4 (rev 13) 00:05.0 PCI bridge: Intel Corporation 5520/X58 I/O Hub PCI Express Root Port 5 (rev 13) 00:06.0 PCI bridge: Intel Corporation 5520/X58 I/O Hub PCI Express Root Port 6 (rev 13) 00:07.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 7 (rev 13) 00:08.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 8 (rev 13) 00:09.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 9 (rev 13) 00:0a.0 PCI bridge: Intel Corporation 5520/5500/X58 I/O Hub PCI Express Root Port 10 (rev 13) 00:0d.0 Host bridge: Intel Corporation Device 343a (rev 13) 00:0d.1 Host bridge: Intel Corporation Device 343b (rev 13) 00:0d.2 Host bridge: Intel Corporation Device 343c (rev 13) 00:0d.3 Host bridge: Intel Corporation Device 343d (rev 13) 00:0d.4 Host bridge: Intel Corporation 5520/5500/X58 Physical Layer Port 0 (rev 13) 00:0d.5 Host bridge: Intel Corporation 5520/5500 Physical Layer Port 1 (rev 13) 00:0d.6 Host bridge: Intel Corporation Device 341a (rev 13) 00:0e.0 Host bridge: Intel Corporation Device 341c (rev 13) 00:0e.1 Host bridge: Intel Corporation Device 341d (rev 13) 00:0e.2 Host bridge: Intel Corporation Device 341e (rev 13) 00:0e.3 Host bridge: Intel Corporation Device 341f (rev 13) 00:0e.4 Host bridge: Intel Corporation Device 3439 (rev 13) 00:14.0 PIC: Intel Corporation 5520/5500/X58 I/O Hub System Management Registers (rev 13) 00:14.1 PIC: Intel Corporation 5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers (rev 13)

Linux平台下IPMI驱动程序设计与实现

中南大学 硕士学位论文 Linux平台下IPMI驱动程序设计与实现 姓名:李号双 申请学位级别:硕士 专业:计算机应用技术 指导教师:陈志刚 20090513

第一章绪论 1.1课题的研究背景 高度信息化的企业或组织都拥有为数众多的服务器,这些服务器保证公司各项生产、电子化服务的正常运作,如公司内部的ERP系统,银行交易系统、生产制造部门的库存系统、学校选课系统等,这些系统软件都是运行在专用的服务器上。若是这些服务器发生问题,将会对使用者产生不小影响,甚至造成组织极大的混乱。如果所有事情都要回到人工处理(如选课系统故障,要改为人工选课)或是整个公司产品生产因此停顿(如数据库系统故障,无法列出正确资产清单),所以维持这些服务器处于良好运行便显得十分重要。 网络的出现对服务器管理是个重大的影响,管理不再是局限于几台桌面计算机,而是通过网络技术,将百台以上的计算机组织起来集中管理,因此远程管理的能力也非常重要。 对拥有大量主机系统的组织来说,二十四小时地监控三、四十部以上的主机运行状况是一个庞大的工程。因此在1998年,Intel、DELL、HP及NEC便共同提出了IPMIv1.0(IntelligentPlatformManagementInterface)规格I¨,作为DMTFl5】标准的一部分,它提供了一个可以跨平台的标准来规范系统内各种硬件的健康状况,如CPU的运行、风扇转速、系统温度及电压等。在不同的处理器、不同BIOS、操作系统下,都可以提供识别信息、监测、运行和复原记录的功能。管理者可以将要监控的部分,设置临界值,在IPMI控制器检测到不正常状况时,可以通过发E.mail、SNMP(SimpleNetworkManagementProtoc01)Trap、灯号、或蜂鸣声来通知系统管理者处理问题。长期不问断地监控、保持机器无差错运行并不是一件容易的事,而服务器管理系统的主要目的便是用来减轻这个负担。 监控系统运行健康状况的能力可说是服务器管理当中最重要的功能,因为不论其它附属的功能有多强大,只要被监控的系统崩溃,其它模块根本无法发挥作用【281,而IPMI最主要的目的就是拿来监控系统运行健康状况,目前开源社群已开发许多遵循IPMI协议的IPMI应用程序。这些软件都遵照规定的相关步骤实现。其好处是,使用者可很容易以开源的IPMI应用程序为基础,也遵照IPMI协议的规范,开发特定的IPMI应用程序;再通过和其它系统信息软件搭配来提供系统监控功能,这样便可以构建服务器管理软件。然而所有的IPMI应用程序(如IntelIPMIConformanceTestSuite和OpenlPMI)其驱动程序都必须通过IPMI协议规定的四个系统接121KCS(KeyboardControllerStyle)、SMIC(ServerManagementInterfaceChip)、BT(BlockTransfer)、SSIF(SMbusSystem

Linux设备驱动编程模型(基本编)

Linux设备驱动程序设计 15年来,Linux从一份大学生的作业演变成了Windows最强劲的竞争对手,在网络、企业、政府和 消费电子市场中逐步占据了重要的地位,在有些领域甚至成了最主要的角色。15年来,Linux在欧洲、在美国、在亚洲向微软发起强劲挑战,以至微软CEO鲍尔默一度相信微软会被Linux击败。 随着Linux进入嵌入式设备领域后,关注和投身Linux开发的开发人员越来越多,但目前市面上介绍Linux开发的资料却非常稀少,很多开发人员感到入行无门,我参照《Linux驱动开发详解》(华清远见,宋宝华)以及其他一些参考资料,编写了本教案,由于时间仓促,没有对应制作相关的ppt,请同学们谅解,希望能给大家一些帮助。 在讲课之前,我们预备把所有的参考资料都列举出来,详细的知识点请大家去对应查找我们所列出的 参考书籍。 1、《Linux程序设计》(人民邮电出版社,陈健等译第3版本)主要关注第18章 2、《Linux驱动开发详解》(华清远见,宋宝华) 3、《嵌入式设计及Linux驱动开发指南-基于ARM9处理器(第2版)》(电子工业出版社,孙天泽) 4、《嵌入式软件调试技术》(电子工业出版社,罗克露等) 5、《嵌入式Linux应用开发详解》(电子工业出版社,洗进等) 6、《嵌入式Linux程序设计案例与实验教程》(机械工业出版社,俞辉) 7、《嵌入式系统课程设计》(机械工业出版社,陈虎等) 还有一些互连网资料,这里就不一一列举了。请大家尽量去找这些资料进行学习。 第一讲Linux设备驱动编程之引言 目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer):主要利用C库函数和Linux API进行应用软件的编写; (2)Linux固件工程师(Firmware Engineer):主要进行Bootloader、Linux的移植及Linux设备驱动程序的设计。 一般而言,固件工程师的要求要高于应用软件工程师的层次,而其中的Linux设备驱动编程又是Linux 程序设计中比较复杂的部分,究其原因,主要包括如下几个方面: (1)设备驱动属于Linux内核的部分,编写Linux设备驱动需要有一定的Linux操作系统内核基础; (2)编写Linux设备驱动需要对硬件的原理有相当的了解,大多数情况下我们是针对一个特定的嵌 入式硬件平台编写驱动的; (3)Linux设备驱动中广泛涉及到多进程并发的同步、互斥等控制,容易出现bug; (4)由于属于内核的一部分,Linux设备驱动的调试也相当复杂。 目前,市面上的Linux设备驱动程序参考书籍非常稀缺,少有的经典是由Linux社区的三位领导者Jonathan Corbet、Alessandro Rubini、Greg Kroah-Hartman编写的《Linux Device Drivers》(目前该书

linux无线网络配置无线网卡驱动安装与wlan802.11配置

Linux无线网络配置——无线网卡驱动安装与WLAN 802.11 配置 Linux无线网络配置——无线网卡驱动安装与WLAN 802.11配置2008-05-10 18:27 20739人阅读 评论(5) 收藏 举报 Linux无线网络配置 ——无线网卡驱动安装与WLAN 802.11配置 WLAN (Wireless Local Area Network)类似于有线以太网,WLAN 的802.11a 标准使用5 GHz 频段,支持的最大速度为54 Mbps,而802.11b 和802.11g 标准使用2.4 GHz 频段,分别支持最大11 Mbps 和54 Mbps 的速度。使用Windows操作系统,WLAN配置很简单。无线网卡厂 商将Windows下的驱动随网卡一起销售。而Linux新兴的操作系统,这方面的驱动不多。以前购买无线网卡时也没考虑Linux下的驱动程序,于是需要编译驱动程序源码。 现在市场上大部分的无线网卡都是对于Atheros芯片的。

如TP—LINK的310G、350G、510G、550G、650G。对于Atheros芯片的网卡,可以到https://www.360docs.net/doc/246579061.html,网站上找到驱动程序,根据源代码包里面的README和INSTALL文件来获得足够的安装信息。最新驱动源码包(0.9.2版本)下载地址 https://www.360docs.net/doc/246579061.html,/madwifi/madwifi-0.9.2.tar .bz2?modtime=1154005765&big_mirror=0 下面详细介绍无线网卡驱动程序的安装和WLAN的配置。操作步骤: 下载驱动源码包存放在/root/downloads目录下 步骤一、解压源码压缩包 1). 进入文件所在目录 cd /root/downloads 2). 解压.bz2格式的压缩包 bunzip2 madwifi-0.9.2.tar.bz2 生成.tar格式压缩包 3). 解压.tar格式的压缩包 tar xvf madwifi-0.9.2.tar 步骤二、编译安装驱动

编写嵌入式Linux设备驱动程序的实例教程

编写嵌入式Linux设备驱动程序的实例教程 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1、对设备初始化和释放; 2、把数据从内核传送到硬件和从硬件读取数据; 3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4、检测和处理设备出现的错误。 在linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如

果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把

相关文档
最新文档