网卡从24c02获取设置mac地址

本文档详细介绍了如何在Linux内核中通过i2c接口从24c02 EEPROM读取并设置网卡的MAC地址。在探究驱动初始化顺序后,确定了在i2c子系统初始化后进行MAC地址操作的策略。通过添加自定义的读写函数,并在探测阶段调用它们,确保了网卡能正确获取MAC地址。同时,利用i2c-tools工具验证了24c02中的数据读写,以确保MAC地址设置无误。
#include <linux/kernel.h>
#include <linux/types.h>

#include <linux/i2c.h>

unsigned char mac_read(unsigned char command)
{
	int ret;
	unsigned char buf;
	struct i2c_adapter *a = i2c_get_adapter(1);
	struct i2c_msg msg[2] = 
	{
		{ 
		.addr = 0x50, .flags = 0, .buf = &command, .len = 1
		},
		
		{
		.addr = 0x50, .flags = I2C_M_RD, .buf = &buf, 	.len = 1
		}
	};
	
	ret = i2c_transfer(a, msg, 2);
	if (ret < 0) {
		printk("[mac_write] i2c_transfer error\n");
	}

	return buf;
}
EXPORT_SYMBOL(mac_read);

int mac_write(unsigned char reg, unsigned char data)
{
	int ret;
	unsigned char buf [] = { reg, data };
	struct i2c_adapter *a = i2c_get_adapter(1);
	struct i2c_msg msg[1] = 
	{
		{ 
			.addr = 0x50, .flags = 0, .buf = buf, .len = 2 
		}
	};

	ret = i2c_transfer(a, msg, 1);
	if (ret < 0) {
		printk("[mac_write] i2c_transfer error\n");
	}

	return ret;
}
EXPORT_SYMBOL(mac_write);

写这个程序之前我在思考是网卡先驱动获取mac先呢,还是i2c子系统的i2c适配器先初始化好呢?

加了些打印语句判断之后,证明我的板子是i2c子系统的i2c适配器先初始化好,于是可以堂而皇之的用i2c接口的api

如果不是就得用__raw_writew,__raw_readw这些底层寄存器操作函数,像单片机一样来读取mac地址,

不然网卡获取不到固定mac,ip在dhcp获取中就会变动,

写入不着急可以等到i2c子系统初始化好再说

 

先修改makefile添加该c文件的依赖,让它编译进内核

(这里我调试板子使用nfs的,内核存放于sd卡中,正常逻辑我每次改内核就得把sd拿出来拷贝一次,相当的麻烦

我把sd卡挂载在/media/card中,内核编译后uImage自动复制一份到nfs目录中,超级终端中利用cp命令将unfs目录中的Image复制到挂载的/media/card目录下,替换掉旧的uImage)


在网卡驱动中添加声明

extern unsigned char mac_read(unsigned char command);
extern int mac_write(unsigned char reg, unsigned char data);

在网卡平台设备的probe中这样引用

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

    pdata->mac_addr[i] = mac_read(i+offset);   //读方法的调用

printk("eth%s MAC addr:",(offset==1)?"0":"1");
 printk("%pM\n", pdata->mac_addr);

双网卡的所以有个不同的offset偏移量,表示mac地址在24c02的偏移位置

 

下面有代码

 if (!is_valid_ether_addr(priv->mac_addr)) {    //判断mac地址是否存在,就是24c02是否写入了合适的mac地址了
  /* Use random MAC if none passed */
  random_ether_addr(priv->mac_addr);    //没有的话会产生随机的mac地址
  printk(KERN_WARNING "%s: using random MAC addr: %pM\n",
    __func__, priv->mac_addr);
  for (i = 0; i < 6; i++){

   mac_write(offset+i,priv->mac_addr[i]);   //那么就将随机分配的mac地址写入24c02中,省点事去往24c02烧mac地址
   msleep(1);  //加个延时 写太快 有时候会写失败
  }
 }

读方法会打印出来结果

写方法用i2c工具在应用层查看写入是否与自己期望值一样

移植i2c-tools

1.官方网站下载http://www.lm-sensors.org/wiki/I2CTools
i2c-tools-3.1.0.tar.bz2

2.解压
tar -xvf i2c-tools-3.1.0.tar.bz2
3.修改makefile
CC =gcc -> CC = arm-none-linux-gnueabi-gcc

4.make编译

5.将tools目录下i2cdetect、i2cdump、i2cget、i2cset拷贝到目标板文件系统/bin目录下

i2c工具介绍

i2cdetect – 用來列舉I2C bus和上面所有的裝置 
i2cdump – 顯示裝置上所有register的值 
i2cget – 讀取裝置上某個register的值 
i2cset – 寫入裝置上某個register 

加上-V参数可以查看工具的版本信息

用户:  i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]
       i2cdetect -F I2CBUS
       i2cdetect -l
  I2CBUS是一个整数或提供的i2c总线名
  FIRST和LAST是限定的探测范围

先检测适配器

# i2cdetect -l
i2c-1   i2c             OMAP I2C adapter                        I2C adapter
i2c-2   i2c             OMAP I2C adapter                        I2C adapter

检测适配器功能

# i2cdetect -F 1
Functionalities implemented by /dev/i2c-1:
I2C                              yes
SMBus Quick Command              no    //不支持quick command -q参数就不能用
SMBus Send Byte                  yes
SMBus Receive Byte               yes
SMBus Write Byte                 yes
SMBus Read Byte                  yes
SMBus Write Word                 yes
SMBus Read Word                  yes
SMBus Process Call               yes
SMBus Block Write                yes
SMBus Block Read                 no
SMBus Block Process Call         no
SMBus PEC                        yes
I2C Block Write                  yes
I2C Block Read                   yes

扫描有哪些i2c设备

# i2cdetect -r 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] 

会询问按回车

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 51 52 53 54 55 56 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --   

如果嫌确认麻烦可以加上-y选项,该选项表示不用用户确认默认确定
0x50是我的24c02

用法: i2cdump [-f] [-y] [-r first-last] I2CBUS ADDRESS [MODE [BANK [BANKREG]]]
  I2CBUS是一个整数或提供的i2c总线名
  ADDRESS是一个整数(0x03 - 0x77)
  MODE是一下之一:
    b (字节, 默认)
    w (字)
    W (word on even register addresses)
    s (SMBus 块)
    i (I2C 块)
    c (连续字节)
    Append p for SMBus PEC

接着用i2cdump查看某设备的所有寄存器的数据

# i2cdump -y 1 0x50 b
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 72 f9 96 0d 75 ea 00 7f 92 b9 ea d4 12 fd 01    .r???u?.????????
10: 33 12 01 04 08 a0 5a 78 0a 01 c1 a0 57 47 98 27    3?????Zx????WG?'
20: 12 4c 4c a1 08 00 31 40 45 40 61 40 81 80 a9 40    ?LL??.1@E@a@???@
30: 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c    ???????:??q8-@X,
40: 46 00 40 84 63 00 00 1e 66 21 50 b0 51 00 1b 30    F.@?c..?f!P?Q.?0
50: 40 70 36 00 40 84 63 00 00 1e 00 00 00 fd 00 39    @p6.@?c..?...?.9
60: 3f 1e 50 0f 00 0a 20 20 20 20 20 20 00 00 00 fc    ??P?.?      ...?
70: 00 4c 43 44 54 56 31 34 0a 20 20 20 20 20 00 c2    .LCDTV14?     .?
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................

i2c获取和设置的工具

用法: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]
  I2CBUS是一个整数或提供的i2c总线名
  ADDRESS是一个整数(0x03 - 0x77)
  MODE是一下之一:
    b (读字节数据,默认)
    w (读字数据)
    c (写字节/读字节)
    Append p for SMBus PEC
用法: i2cset [-f] [-y] [-m MASK] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE] [MODE]
  I2CBUS是一个整数或提供的i2c总线名
  ADDRESS是一个整数(0x03 - 0x77)
  MODE是一下之一:
    c (字节,无值)
    b (字节数据,默认)
    w (字数据)
    Append p for SMBus PEC

获取寄存器数据

# i2cget -y 1 0x50 0x10
0x33

设置寄存器数据

# i2cset -y 1 0x50 0x10 0xAB

再次获取

# i2cget -y 1 0x50 0x10
0xab

值已经变了








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值