linux怎么测试网卡移植成功,【Linux高级驱动】如何分析并移植网卡驱动

dm9000的驱动分析

m9000_init

platform_driver_register(

&dm9000_driver);

dm9000_probe

/*获取平台数据*/

struct dm9000_plat_data

*pdata

= pdev

-

>dev.platform_data;

/*表示一个网络设备*/

struct net_device

*ndev;

/*为网络设备分配空间*/

ndev

= alloc_etherdev(

sizeof(

struct board_info));

/*获取资源*/

db

-

>addr_res

= platform_get_resource(pdev, IORESOURCE_MEM,

0);

db

-

>data_res

= platform_get_resource(pdev, IORESOURCE_MEM,

1);

db

-

>irq_res

= platform_get_resource(pdev, IORESOURCE_IRQ,

0);

/*映射地址端口*/

db

-

>io_addr

= ioremap(db

-

>addr_res

-

>start, iosize);

/*映射数据端口*/

db

-

>io_data

= ioremap(db

-

>data_res

-

>start, iosize);

/*硬件相关的操作*/

/*1.设置读写操作函数*/

dm9000_set_io(db,

2);

case

2

:

db

-

>dumpblk

= dm9000_dumpblk_16bit;

db

-

>outblk

= dm9000_outblk_16bit;

db

-

>inblk

= dm9000_inblk_16bit;

break;

/*2.复位 */

dm9000_reset(db);

/*3.读dm9000的ID号 */

id_val

= ior(db, DM9000_VIDL);

id_val

|= (u32)ior(db, DM9000_VIDH)

<<

8;

id_val

|= (u32)ior(db, DM9000_PIDL)

<<

16;

id_val

|= (u32)ior(db, DM9000_PIDH)

<<

24;

/* 获取芯片型号 */

id_val

= ior(db, DM9000_CHIPR);

ether_setup(ndev);

/*设置操作方法*/

ndev

-

>netdev_ops

=

&dm9000_netdev_ops;

/*注册网络设备*/

register_netdev(ndev);

//register_chrdev

cs8900a网卡驱动分析

/*分配一个网络设备*/

struct net_device

*dev

= alloc_etherdev(

sizeof(

struct net_local));

dev

-

>irq

= irq;

dev

-

>base_addr

= io;

cs89x0_probe1(dev, io,

1);

/*识别芯片*/

/*操作方法的设置*/

dev

-

>netdev_ops

=

&net_ops;

/*注册网络设备*/

register_netdev(dev);

static

const

struct net_device_ops dm9000_netdev_ops

= {

.ndo_open

= dm9000_open,

//必须的

.ndo_stop

= dm9000_stop,

//必须的

.ndo_start_xmit

= dm9000_start_xmit,

//必须的

.ndo_tx_timeout

= dm9000_timeout,

//必须的

.ndo_set_multicast_list

= dm9000_hash_table,

.ndo_do_ioctl

= dm9000_ioctl,

.ndo_change_mtu

= eth_change_mtu,

.ndo_validate_addr

= eth_validate_addr,

.ndo_set_mac_address

= eth_mac_addr,

#

ifdef CONFIG_NET_POLL_CONTROLLER

.ndo_poll_controller

= dm9000_poll_controller,

#

endif

};

网卡驱动的数据接收发送流程?

初始化设备

dm9000_open(

struct net_device

*dev)

{

if (request_irq(dev

-

>irq, dm9000_interrupt, irqflags, dev

-

>name, dev))

return

-EAGAIN;

/* Initialize DM9000 board */

dm9000_reset(db);

/* RESET device */

writeb(DM9000_NCR, db

-

>io_addr);

udelay(

200);

writeb(NCR_RST, db

-

>io_data);

udelay(

200);

/* dm9000的初始化,芯片厂商会支持 */

dm9000_init_dm9000(dev);

/* 启动发送队列 */

netif_start_queue(dev);

}

数据接收流程

dm9000_interrupt(

int irq,

void

*dev_id)

/* Save previous register address */

reg_save

= readb(db

-

>io_addr);

/* Disable all interrupts */

iow(db, DM9000_IMR, IMR_PAR);

/* Got DM9000 interrupt status */

int_status

= ior(db, DM9000_ISR);

/* Got ISR */

iow(db, DM9000_ISR, int_status);

/* Clear ISR status */

/* Received the coming packet 读中断*/

if (int_status

& ISR_PRS)

dm9000_rx(dev);

ior(db, DM9000_MRCMDX);

/* Dummy read 地址不自动增加*/

rxbyte

= readb(db

-

>io_data);

if (rxbyte

& DM9000_PKT_ERR) {

dev_warn(db

-

>dev,

"status check fail: %d\n", rxbyte);

iow(db, DM9000_RCR, 0x00);

/* Stop Device */

iow(db, DM9000_ISR, IMR_PAR);

/* Stop INT request */

return;

}

writeb(DM9000_MRCMD, db

-

>io_addr);

/*地址自动增加的*/

/* 读取状态信息 */

(db

-

>inblk)(db

-

>io_data,

&rxhdr,

sizeof(rxhdr));

//dm9000_inblk_16bit

RxLen

= le16_to_cpu(rxhdr.RxLen);

/*数据的状态判断*/

if (rxhdr.RxStatus

& (RSR_FOE

| RSR_CE

| RSR_AE

|

RSR_PLE

| RSR_RWTO

|

RSR_LCS

| RSR_RF)) {

struct sk_buff

*skb;

skb

= dev_alloc_skb(RxLen

+

4))

/*分配一个sk_buff数据包*/

skb_reserve(skb,

2);

//data指针和tail指针同时下移

rdptr

= (u8

*) skb_put(skb, RxLen

-

4);

(db

-

>inblk)(db

-

>io_data, rdptr, RxLen);

//dm9000_inblk_16bit   //读真正的有效数据(MAC头,TCP头,IP头,网络数据)

dev

-

>stats.rx_bytes

+= RxLen;

/* Pass to upper layer,去掉MAC头 */

skb

-

>protocol

= eth_type_trans(skb, dev);

/* 将数据上报到上层 */

netif_rx(skb);

dev

-

>stats.rx_packets

++;

数据发送流程

sk_buff

dm9000_start_xmit

/* 将数据写入到DM9000的SRAM中 */

/* Move data to DM9000 TX RAM */

writeb(DM9000_MWCMD, db

-

>io_addr);

//设置为自动增加

//dm9000_outblk_16bit

(db

-

>outblk)(db

-

>io_data, skb

-

>data, skb

-

>len);

//dm9000_outblk_16bit

dev

-

>stats.tx_bytes

+= skb

-

>len;

db

-

>tx_pkt_cnt

++;

/*设置发送属性*/

dm9000_send_packet(

struct net_device

*dev,

int ip_summed,

u16 pkt_len)

/*指定数据包的长度*/

iow(dm, DM9000_TXPLL, pkt_len);

iow(dm, DM9000_TXPLH, pkt_len

>>

8);

/*启动发送:数据发送完成,产生中断*/

iow(dm, DM9000_TCR, TCR_TXREQ);

/* Cleared after TX complete */

netif_stop_queue(dev);

dm9000_interrupt(

int irq,

void

*dev_id)

/* Save previous register address */

reg_save

= readb(db

-

>io_addr);

//让他不自动增加

/* 关中断 */

iow(db, DM9000_IMR, IMR_PAR);

/*获取中断状态*/

int_status

= ior(db, DM9000_ISR);

/* Got ISR */

iow(db, DM9000_ISR, int_status);

/* Clear ISR status */

/* Trnasmit Interrupt check,数据发送完成 */

if (int_status

& ISR_PTS)

dm9000_tx_done(dev, db);

db

-

>tx_pkt_cnt

--;

dev

-

>stats.tx_packets

++;

if (db

-

>tx_pkt_cnt

>

0)

dm9000_send_packet(dev, db

-

>queue_ip_summed,db

-

>queue_pkt_len);

/*指定数据包的长度*/

iow(dm, DM9000_TXPLL, pkt_len);

iow(dm, DM9000_TXPLH, pkt_len

>>

8);

/*启动发送:数据发送完成,产生中断*/

iow(dm, DM9000_TCR, TCR_TXREQ);

/* Cleared after TX complete */

netif_wake_queue(dev);

/* Re-enable interrupt mask */

iow(db, DM9000_IMR, db

-

>imr_all);

/* Restore previous register address */

writeb(reg_save, db

-

>io_addr);

//恢复为自动增加

怎么写网卡驱动

1.cs89x0.c

1.1 分配一个net_device结构体

alloc_etherdev

1.2 设置

dev

-

>open

= net_open;

dev

-

>stop

= net_close;

dev

-

>tx_timeout

= net_timeout;

dev

-

>watchdog_timeo

= HZ;

dev

-

>hard_start_xmit

= net_send_packet;

dev

-

>get_stats

= net_get_stats;

dev

-

>set_multicast_list

= set_multicast_list;

dev

-

>set_mac_address

= set_mac_address;

1.3 注册

register_netdev

2. DM9000.c

2.1 分配一个net_device结构体

ndev = alloc_etherdev(sizeof (struct board_info));

2.2 设置

ether_setup(ndev);

ndev

-

>open

=

&dm9000_open;

ndev

-

>hard_start_xmit

=

&dm9000_start_xmit;

ndev

-

>tx_timeout

=

&dm9000_timeout;

ndev

-

>watchdog_timeo

= msecs_to_jiffies(watchdog);

ndev

-

>stop

=

&dm9000_stop;

ndev

-

>get_stats

=

&dm9000_get_stats;

ndev

-

>set_multicast_list

=

&dm9000_hash_table;

2.3 注册

ret = register_netdev(ndev);

任何设备的核心都是收发数据

1. 发数据:

上层要发送数据时,构造一个sk_buff,然后调用net_device的hard_start_xmit来发送

2. 收数据:

网卡收到数据后,发生中断

在中断服务程序里:

从硬件上读出数据,然后构造一个sk_buff,上报:

a. 分配一个sk_buff结构体:

dev_alloc_skbb. 使用硬件上得到数据填充这个结构体

c. 上报:netif_rx

测试方法

1. 编译/安装驱动 farsight_net_1.c

ifconfig fs_net0 up

ifconfig fs_net0

192.

188.

1.

1

ping

192.

188.

1.

1 成功,证明ping自己的话,不经过硬件

ping

192.

188.

1.

2 多次调用fsnet_hard_start_tx

PING

192.

188.

1.

2 (

192.

188.

1.

2)

:

56 data bytes

fsnet_hard_start_tx

fsnet_hard_start_tx

再次ifconfig发现fs_net0的rx/tx都是0

2. 编译/安装驱动 farsight_net_2.c: 添加统计信息

3. 编译/安装驱动 farsight_net_3.c: 设MAC地址

ifconfig fs_net0

ifconfig         可以看到MAC地址

4. 编译/安装驱动 farsight_net_4.c: 构造ping的返回包

ifconfig fs_net0 up

ifconfig fs_net0 192.188.1.1

ping 192.188.1.2                成功

怎么移植网卡驱动

网卡基本上都是内存接口(ram-like)    1. 根据原理图确定访问地址, 在驱动里修改相应项

2. 为了能通过这些地址访问网卡,对于2410还要设置memory controller

比如设置位宽、时间参数

3. 根据原理图确定中断号, 在驱动里修改相应项(包括中断号、中断触发方式(高/低有效))

@成鹏致远

(blogs:http://lcw.cnblogs.com)

(email:wwwlllll@126.com)

(qq:552158509)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值