新路程------imx6 網絡卡驅動(1)
阿新 • • 發佈:2019-01-22
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;
}
暫時先寫這麼多,關於網路裝置的那些配置資訊怎麼來的將後面再寫