stmmac probe 過程

來源:互聯網
上載者:User

本文以海思3535的stmmac驅動註冊過程為例,介紹網路驅動探測、網路裝置探測過程。原文地址  http://blog.csdn.net/linchuanzhi_886/article/details/44458713

1.由於我們使用的是乙太網路,直接用alloc_etherdev()函數返回一個struct net_device的地址ndev。 
在alloc_ether的過程中,會把ndev->dev->name賦值為“eth%” 
2. 第一步成功後,擷取STMMAC的資源,包括記憶體、中斷。 
3. 初始化mac資訊。主要是根據mac控制器的能力,給mac_device_info結果體成員賦值。如全/半雙工模式、10/100/1000Mbps,並且讀取mac地址,如果mac地址無效,自動分配一個mac地址。裡面有DMA操作函數。 
4. `static int stmmac_mac_device_setup(struct net_device *dev) 

struct stmmac_priv *priv = netdev_priv(dev);

struct mac_device_info *device;if (priv->plat->has_gmac)    device = dwmac1000_setup(priv->ioaddr);else    device = dwmac100_setup(priv->ioaddr);if (!device)    return -ENOMEM;if (priv->plat->enh_desc) {    device->desc = &enh_desc_ops;    pr_info("\tEnhanced descriptor structure\n");} else    device->desc = &ndesc_ops;****priv->hw = device;****return 0;


`

struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr){    struct mac_device_info *mac;    u32 uid = readl(ioaddr + GMAC_VERSION);    printk("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n",        ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff));    mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);    if (!mac)        return NULL;    mac->mac = &dwmac1000_ops;    mac->dma = &dwmac1000_dma_ops;    mac->link.port = GMAC_CONTROL_PS;    mac->link.duplex = GMAC_CONTROL_DM;    mac->link.speed = GMAC_CONTROL_FES;    mac->mii.addr = GMAC_MII_ADDR;    mac->mii.data = GMAC_MII_DATA;    return mac;}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
const struct stmmac_dma_ops dwmac1000_dma_ops = {    .init = dwmac1000_dma_init,    .dump_regs = dwmac1000_dump_dma_regs,    .dma_mode = dwmac1000_dma_operation_mode,    .enable_dma_transmission = dwmac_enable_dma_transmission,    .enable_dma_irq = dwmac_enable_dma_irq,    .disable_dma_irq = dwmac_disable_dma_irq,    .start_tx = dwmac_dma_start_tx,    .stop_tx = dwmac_dma_stop_tx,    .start_rx = dwmac_dma_start_rx,    .stop_rx = dwmac_dma_stop_rx,    .dma_interrupt = dwmac_dma_interrupt,    .get_hw_feature = dwmac1000_get_hw_feature,};static const struct stmmac_ops dwmac1000_ops = {    .core_init = dwmac1000_core_init,    .rx_coe = dwmac1000_rx_coe_supported,    .dump_regs = dwmac1000_dump_regs,    .host_irq_status = dwmac1000_irq_status,    .set_filter = dwmac1000_set_filter,    .flow_ctrl = dwmac1000_flow_ctrl,    .pmt = dwmac1000_pmt,    .set_umac_addr = dwmac1000_set_umac_addr,    .get_umac_addr = dwmac1000_get_umac_addr,};
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

4.ether_setup(dev);設定ndev的頭部資訊:

void ether_setup(struct net_device *dev){    dev->header_ops     = &eth_header_ops;    dev->type       = ARPHRD_ETHER;//1    dev->hard_header_len    = ETH_HLEN;//14    dev->mtu        = ETH_DATA_LEN;//1500    dev->addr_len       = ETH_ALEN;//6    dev->tx_queue_len   = 1000; /* Ethernet wants good queues */    dev->flags      = IFF_BROADCAST|IFF_MULTICAST;    dev->priv_flags     |= IFF_TX_SKB_SHARING;    memset(dev->broadcast, 0xFF, ETH_ALEN);}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

填充ndev的netdev_ops,實現網路裝置的open、發生,停止,逾時處理函數,ioctl調用。 
`static const struct net_device_ops stmmac_netdev_ops = { 
.ndo_open = stmmac_open, 
.ndo_start_xmit = stmmac_xmit, 
.ndo_stop = stmmac_release, 
.ndo_change_mtu = stmmac_change_mtu, 
.ndo_set_rx_mode = stmmac_multicast_list, 
.ndo_tx_timeout = stmmac_tx_timeout, 
.ndo_do_ioctl = stmmac_ioctl, 
.ndo_set_config = stmmac_config, ifdef STMMAC_VLAN_TAG_USED

.ndo_vlan_rx_register = stmmac_vlan_rx_register,
endif ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = stmmac_poll_controller,
endif
.ndo_set_mac_address = stmmac_eth_mac_addr,

};` 現在核心基本都支援ETHTOOL,填充ndev的ethtooll_ops。 
( (netdev)->ethtool_ops = (ops)

static struct ethtool_ops stmmac_ethtool_ops = {    .begin = stmmac_check_if_running,    .get_drvinfo = stmmac_ethtool_getdrvinfo,    .get_settings = stmmac_ethtool_getsettings,    .set_settings = stmmac_ethtool_setsettings,    .get_msglevel = stmmac_ethtool_getmsglevel,    .set_msglevel = stmmac_ethtool_setmsglevel,    .get_regs = stmmac_ethtool_gregs,    .get_regs_len = stmmac_ethtool_get_regs_len,    .get_link = ethtool_op_get_link,    .get_pauseparam = stmmac_get_pauseparam,    .set_pauseparam = stmmac_set_pauseparam,    .get_ethtool_stats = stmmac_get_ethtool_stats,    .get_strings = stmmac_get_strings,    .get_wol = stmmac_get_wol,    .set_wol = stmmac_set_wol,    .get_sset_count = stmmac_get_sset_count,};6.設定watchdog_timeo時間在前5步,也可以初始化mac_device_info,並實現其mdio_bus匯流排的度磁軛7.register_netdev(ndev)註冊到核心。產生eth0/1/2節點。8.初始化mdiobus讀寫函數,並註冊bus->dev,接著探測mii匯流排上的phy。發現有效phy之後,執行phy_device_create、phydev_register.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

static struct mii_bus *stmmac_mii_bus; 
int stmmac_mdio_register(struct net_device *ndev) 

……. 
stmmac_mii_bus->name = “STMMAC MII Bus”; 
stmmac_mii_bus->read = &stmmac_mdio_read; 
stmmac_mii_bus->write = &stmmac_mdio_write; 
stmmac_mii_bus->reset = &stmmac_mdio_reset; 
snprintf(stmmac_mii_bus->id, MII_BUS_ID_SIZE, “%x”, 
priv->plat->bus_id); 
stmmac_mii_bus->priv = ndev; 
stmmac_mii_bus->irq = irqlist; 
stmmac_mii_bus->phy_mask = priv->phy_mask; 
stmmac_mii_bus->parent = priv->device; 
err = mdiobus_register(stmmac_mii_bus); 
…… 

int mdiobus_register(struct mii_bus *bus) 

int i, err;

if (NULL == bus || NULL == bus->name ||        NULL == bus->read ||        NULL == bus->write)    return -EINVAL;BUG_ON(bus->state != MDIOBUS_ALLOCATED &&       bus->state != MDIOBUS_UNREGISTERED);bus->dev.parent = bus->parent;bus->dev.class = &mdio_bus_class;bus->dev.groups = NULL;dev_set_name(&bus->dev, "%s", bus->id);err = device_register(&bus->dev);if (err) {    printk(KERN_ERR "mii_bus %s failed to register\n", bus->id);    return -EINVAL;}mutex_init(&bus->mdio_lock);if (bus->reset)    bus->reset(bus);for (i = 0; i < PHY_MAX_ADDR; i++) {    if ((bus->phy_mask & (1 << i)) == 0) {        struct phy_device *phydev;        phydev = mdiobus_scan(bus, i);        if (IS_ERR(phydev)) {            err = PTR_ERR(phydev);            goto error;        }    }}bus->state = MDIOBUS_REGISTERED;pr_info("%s: probed\n", bus->name);return 0;

error: 
while (–i >= 0) { 
if (bus->phy_map[i]) 
device_unregister(&bus->phy_map[i]->dev); 

device_del(&bus->dev); 
return err; 
}

 1 1 

struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) 

struct phy_device *phydev; 
int err;

phydev = get_phy_device(bus, addr);if (IS_ERR(phydev) || phydev == NULL)    return phydev;err = phy_device_register(phydev);if (err) {    phy_device_free(phydev);    return NULL;}return phydev;


struct phy_device * get_phy_device(struct mii_bus *bus, int addr) 

struct phy_device *dev = NULL; 
u32 phy_id; 
int r;

r = get_phy_id(bus, addr, &phy_id);if (r)    return ERR_PTR(r);/* If the phy_id is mostly Fs, there is no device there */if ((phy_id & 0x1fffffff) == 0x1fffffff)    return NULL;dev = phy_device_create(bus, addr, phy_id);return dev;


int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) 

int phy_reg;

/* Grab the bits from PHYIR1, and put them * in the upper half */phy_reg = mdiobus_read(bus, addr, MII_PHYSID1);printk(KERN_INFO "ID1 = 0x%x at %s \n",phy_reg,bus->name);if (phy_reg < 0)    return -EIO;*phy_id = (phy_reg & 0xffff) << 16;/* Grab the bits from PHYIR2, and put them in the lower half */phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);printk(KERN_INFO "ID2 = 0x%x at %s \n",phy_reg,bus->name);if (phy_reg < 0)    return -EIO;*phy_id |= (phy_reg & 0xffff);return 0;

}

9.初始化sk_buff隊列頭,skb_queue_head_init。然後申請中斷,開啟中斷。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.