1. 程式人生 > >新路程------imx6 網絡卡驅動(1)

新路程------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;
}

暫時先寫這麼多,關於網路裝置的那些配置資訊怎麼來的將後面再寫