/*
* 网络驱动的初始化过程
* at91rm9200 - dm9161 - 2.6.20
*/
at91ether_init(void);
|
platform_driver_register(&at91ether_driver);
|
at91ether_probe(struct platform_device *pdev); (pdev在at91rm9200_devices.c中定义)
|
使能时钟
|
循环检测PHY设备.(这里只有一个设备DM9161,所以一次循环就结束)
|
使能mii
|
读取phy_id
|
禁用mii
|
合成phy_id
|
测试phy_id
|
符合DM9161的phy_id
|
/* 初始化以太网接口 */
at91ether_setup(phy_id, phy_address, pdev, ether_clk);
|
/* 获得struct net_device *dev */
dev = alloc_etherdev(sizeof(struct at91_private));
|
获得platform_resource
|
配置dev的base_addr, irq
|
配置网卡的中断和处理例程
|
初始化private中的接收缓冲区及descriptor list,和DMA有关
|
配置private的其他成员变量
|
初始化spin_lock
|
ether_setup(dev);
|
配置net_device *dev的各成员变量:
open = at91ether_open;
stop = at91ether_close;
hard_start_xmit = at91ether_tx;
get_stats = at91ether_stats;
set_multicast_list = at91ether_set_rx_mode;
set_mac_address = set_mac_address;
ethtool_ops = &at91ether_ethtool_ops;
do_ioctl = at91ether_ioctl;
poll_controller = at91ether_poll_controller;
|
从EMAC中取得MAC地址,并存储在dev->dev_addr
并更新到EMAC
|
清空AT91_EMAC_CTL
|
设置是否为RMII模式
|
使能mii, 读取PHY寄存器MII_DSCR_REG,这里判断是否是光纤, 禁用mii.
|
初始化private->mii接口
dev = dev
mdio_read = mdio_read
mdio_write = mdio_write
phy_id = phy_address (这里是0)
phy_id_mask = 0x1f (只有5 bit)
reg_num_mask = 0x1f (只有5 bit)
|
private->phy_type = phy_type (= MII_DM9161_ID = 0x0181b880);
private->phy_address = phy_address (= 0);
|
register_netdev(dev), 注册网络设备struct net_device
/*里面也会初始化很多dev的成员变量*/
|
使能mii
|
update_linkspeed(dev, 0);
从PHY取得连接状态(speed, duplex), 然后对EMAC更新
|
if(!mii_link_ok(&lp->mii));
|
mii->mii_read(...);
读取PHY的状态寄存器,判断是否link
|
<--------
|
如果linked, 读取MII_BMSR, MII_BMCR寄存器
|
从寄存器中得到连接的speed和duplex类型
|
将得到的state更新到EMAC寄存器中
|
netif_carrier_on(dev);通知内核,有连接(载波)
|
<--------
|
禁用mii
|
netif_carrier_off(dev);先通知内核没有连接,以便进行设置
|
如果没有EMAC中断,则设置poll轮询
|
打印ethernet信息
|
<--------
|
循环侦测停止
|
---------
|
禁用时钟
|
返回是否成功探测到设备
|
<--------
|
platform_register_device完成
|
---------
|
退出at91ether_init
|
|<-------
对于不同的内核接口的初始化
* mii接口
这个mii的接口定义在include/linux/mii.h和drivers/net/mii.c中。
主要的初始化工作就是在驱动装载时初始化结构体struct mii_if_info.
struct mii_in_info被装在了private结构体中,为mii.
mii.dev = dev
mii.mdio_read = mdio_read;
mii.mdio_write = mdio_write;
mii.phy_id = phy_address;
mii.phy_id_mask = 0x1f;
mii.reg_num_mask = 0x1f;
以上是在函数at91ether_setup()中完成的.
以后要用到mii接口函数时,只要调用相关mii.c中的函数,并将private.mii
传递给函数即可.
* 内核设备接口 struct net_device
struct net_device定义在include/linux/ntdevice.h.
这个工作同样在at91ether_setup()中完成.函数中为指针dev.
/* 和硬件相关IO基地址和中断号 */
dev->base_addr = res->start;
dev->irq = platform_get_irq(pdev, 0); //pdev为platform_device指针.
platform_set_drvdata(pdev, dev); //means: dev->driver_data = pdev;
ether_setup(dev); //初始化以太网相关数据成员,定义在net/ethernet/eth.c
dev->open = at91ether_open;
dev->stop = at91ether_close;
dev->hard_start_xmit = at91ether_tx;
dev->get_stats = at91ether_stats;
dev->set_multicast_list = at91ether_set_rx_mode;
dev->set_mac_address = set_mac_address;
dev->ethtool_ops = &at91ether_ethtool_ops;
SET_NETDEV_DEV(dev, &pdev->dev); //means: dev->class_dev.dev = &pdev->dev;
get_mac_address(dev); //里面有memcpy(dev->dev_addr, &addr, 6);
dev->do_ioctl = at91ether_ioctl;
dev->poll_controller = at91ether_poll_controller;
阅读(3419) | 评论(0) | 转发(0) |