Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1260280
  • 博文数量: 548
  • 博客积分: 7597
  • 博客等级: 少将
  • 技术积分: 4224
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 13:21
个人简介

嵌入式软件工程师&&太极拳

文章分类

全部博文(548)

文章存档

2014年(10)

2013年(76)

2012年(175)

2011年(287)

分类: 嵌入式

2012-05-09 13:37:29

/*
   * 网络驱动的初始化过程
   * 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;
阅读(3301) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~