新路程------imx6 网卡驱动(1)

  imx6芯片手册上已经写了fec.c是网卡驱动,那么就顺着网卡驱动看看网络设备是怎么建立起来的

static int __devinit
fec_probe(struct platform_device *pdev)
{
	struct fec_enet_private *fep;
	struct fec_platform_data *pdata;
	struct net_device *ndev;  //网络设备的结构体出现了
	int i, irq, ret = 0;
	struct resource *r;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!r)
		return -ENXIO;

	r = request_mem_region(r->start, resource_size(r), pdev->name);
	if (!r)
		return -EBUSY;

	/* Init network device */初始化网络设备
	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
 *	alloc_netdev_mqs - allocate network device
 *	@sizeof_priv:	size of private data to allocate space for
 *	@name:		device name format string
 *	@setup:		callback to initialize device
 *	@txqs:		the number of TX subqueues to allocate
 *	@rxqs:		the number of RX subqueues to allocate
	if (!ndev) {
		ret = -ENOMEM;
		goto failed_alloc_etherdev;
	}

	SET_NETDEV_DEV(ndev, &pdev->dev);

	/* setup board info structure */
	fep = netdev_priv(ndev);

	fep->hwp = ioremap(r->start, resource_size(r));
	fep->pdev = pdev;

	if (!fep->hwp) {
		ret = -ENOMEM;
		goto failed_ioremap;
	}

	platform_set_drvdata(pdev, ndev);

	pdata = pdev->dev.platform_data;
	if (pdata)
		fep->phy_interface = pdata->phy;

	if (pdata->gpio_irq > 0) {
		gpio_request(pdata->gpio_irq, "gpio_enet_irq");
		gpio_direction_input(pdata->gpio_irq);

		irq = gpio_to_irq(pdata->gpio_irq);
		ret = request_irq(irq, fec_enet_interrupt,
				IRQF_TRIGGER_RISING,
				 pdev->name, ndev);
	}
	}

	fep->clk = clk_get(&pdev->dev, "fec_clk");
	
	fep->mdc_clk = clk_get(&pdev->dev, "fec_mdc_clk");
	
	clk_enable(fep->clk);

	ret = fec_enet_init(ndev); //获取eth地址,rx,tx的buffer起始地址
	

	ret = fec_enet_mii_init(pdev); //配置mii bus
	

	if (fec_ptp_malloc_priv(&(fep->ptp_priv))) {
		if (fep->ptp_priv) {
			fep->ptp_priv->hwp = fep->hwp;
			ret = fec_ptp_init(fep->ptp_priv, pdev->id);
			if (ret)
				printk(KERN_WARNING "IEEE1588: ptp-timer is unavailable\n");
			else
				fep->ptimer_present = 1;
		} 
	}

	/* Carrier starts down, phylib will bring it up */
	netif_carrier_off(ndev);
	clk_disable(fep->clk);

	INIT_DELAYED_WORK(&fep->fixup_trigger_tx, fixup_trigger_tx_func);

	ret = register_netdev(ndev);  //网络设备注册
	

	return 0;



	return ret;
}

这里mii bus已经ok了,要把mii bus和phy链接起来的函数是

static int
fec_enet_open(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
	int ret;

	if (fep->use_napi)
		napi_enable(&fep->napi);

	/* I should reset the ring buffers here, but I don't yet know
	 * a simple way to do that.
	 */
	clk_enable(fep->clk);
	ret = fec_enet_alloc_buffers(ndev);
	if (ret)
		return ret;

	/* Probe and connect to PHY when open the interface */  //链接到phy
	ret = fec_enet_mii_probe(ndev);
	if (ret) {
		fec_enet_free_buffers(ndev);
		return ret;
	}

	phy_start(fep->phy_dev);
	netif_start_queue(ndev);
	fep->opened = 1;

	ret = -EINVAL;
	if (pdata->init && pdata->init(fep->phy_dev))
		return ret;

	return 0;
}


这个函数执行之后,数据链路层和物理层就联系起来了

看看这个probe

static int fec_enet_mii_probe(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	struct phy_device *phy_dev = NULL;
	char mdio_bus_id[MII_BUS_ID_SIZE];
	char phy_name[MII_BUS_ID_SIZE + 3];
	int phy_id;
	int dev_id = fep->pdev->id;

	fep->phy_dev = NULL;

	/* check for attached phy */
	for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
		if ((fep->mii_bus->phy_mask & (1 << phy_id)))
			continue;
		if (fep->mii_bus->phy_map[phy_id] == NULL)
			continue;
		if (fep->mii_bus->phy_map[phy_id]->phy_id == 0)
			continue;
		if (dev_id--)
			continue;
		strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
		break;
	}

	if (phy_id >= PHY_MAX_ADDR) {
		printk(KERN_INFO "%s: no PHY, assuming direct connection "
			"to switch\n", ndev->name);
		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
		phy_id = 0;
	}

	snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
	printk("matt===============fec.c\n");

	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,  //这个就是链接函数
		fep->phy_interface);

	
	

	/* enable phy pause frame for any platform */
	phy_dev->supported |= ADVERTISED_Pause;

	phy_dev->advertising = phy_dev->supported;

	fep->phy_dev = phy_dev;
	fep->link = 0;
	fep->full_duplex = 0;

	printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
		"(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
		fep->phy_dev->irq);

	return 0;
}

暂时先写这么多,关于网络设备的那些配置信息怎么来的将后面再写
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值