问题解决了哈,主要是我用的cs8900 驱动里面 修改MAC地址的函数只修改了内存数据结构,没有修改芯片寄存器,我把函数修改了一下,这下可以了。
谢谢 kasim 大侠的提醒哈。看来很多问题还是要自己分析一下才行哦。
首先我查看cs8900的probe 函数 cs8900_probe,在里面定义了初始化的MAC地址保存在驱动的数据结构dev->dev_addr中,代码如下:
dev->dev_addr[0] = 0x08;
dev->dev_addr[1] = 0x00;
dev->dev_addr[2] = 0x1e;
dev->dev_addr[3] = 0x21;
dev->dev_addr[4] = 0xc7;
dev->dev_addr[5] = 0xf8;
紧跟着下面把地址写入到芯片中生效:
for (i = 0; i < ETH_ALEN; i += 2)
cs8900_write (dev,PP_IA + i,dev->dev_addr
| (dev->dev_addr[i + 1] << 8));
PP_IA 为寄存器地址,所以在初始化的时候MAC地址是生效的。
然后我再考虑系统启动后 使用ifconfig 修改 MAC地址,这个时候 ndev->set_mac_address 函数进行操作的。
我检查了一下,我用的这个版本的驱动的cs8900_init 中 没有对此值赋值,而是在ether_setup中赋的缺省函数:
void ether_setup(struct net_device *dev)
{
dev->header_ops = ð_header_ops;
dev->change_mtu = eth_change_mtu;
dev->set_mac_address = eth_mac_addr;
dev->validate_addr = eth_validate_addr;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
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);
}
eth_mac_addr 函数只修改内存数据,没有修改芯片寄存器。
static int eth_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
return 0;
}
我的解决办法就是 自定自己的set_mac_address函数,定义如下
static int cs8900_set_mac_address(struct net_device *dev, void *p)
{
int i;
struct sockaddr *addr = p;
if (netif_running(dev))
return -EBUSY;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
/* set the Ethernet address */
for (i = 0; i < ETH_ALEN; i += 2)
cs8900_write (dev,PP_IA + i,dev->dev_addr | (dev->dev_addr[i + 1] << 8));
return 0;
}
然后在 inint对set_mac_address 赋值就可以了。
static int __init cs8900_init (void)
{
struct net_device *ndev;
ndev = alloc_etherdev(sizeof (cs8900_t));
if (!ndev) {
printk("%s: could not allocate device.\n", "cs8900");
return -ENOMEM;
}
cs8900_dev = ndev;
cs8900_dev->init = cs8900_probe;
ether_setup (ndev);
ndev->open = cs8900_start;
ndev->stop = cs8900_stop;
ndev->hard_start_xmit = cs8900_send_start;
ndev->get_stats = cs8900_get_stats;
ndev->set_multicast_list = cs8900_set_receive_mode;
ndev->tx_timeout = cs8900_transmit_timeout;
ndev->set_mac_address = cs8900_set_mac_address;
ndev->watchdog_timeo = HZ;
return (register_netdev (cs8900_dev));
}[ 此贴被qwetiop在2008-11-23 13:20重新编辑 ]