STMMAC probe Process

Source: Internet
Author: User

This paper takes the Stmmac drive registration process of HiSilicon 3535 as an example to introduce the network-driven detection and network equipment detection process. Original Address http://blog.csdn.net/linchuanzhi_886/article/details/44458713

1. Because we are using Ethernet, we return a struct Net_device address Ndev directly with the Alloc_etherdev () function.
In the process of Alloc_ether, Ndev->dev->name will be assigned to "eth%"
2. After the first step succeeds, obtains the STMMAC resources, including memory, interrupts.
3. Initialize MAC information. It is mainly based on the ability of MAC controller to assign value to Mac_device_info result body member. such as full/Half-duplex mode, 10/100/1000mbps, and read MAC address, if the MAC address is invalid, automatically assign a MAC address. There is a DMA operation function inside.
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;

    U32 uid = READL (ioaddr + gmac_version); PRINTK ("\tdwmac1000-user id:0x%x, Synopsys id:0x%x\n", ((UID & 0x0000ff00) >> 8), (UID & 0x00000

    0FF));
    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
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,. Sto P_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_supp orted,. 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 22 23 24 25 26

4.ether_setup (dev); set Ndev header information:

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

Fill in the Ndev netdev_ops, realize the network device open, occur, stop, timeout processing functions, IOCTL call.
' 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,

' Now the kernel basically supports ethtool, filling the Ndev ethtooll_ops.
((Netdev)->ethtool_ops = (OPS)

static struct Ethtool_ops Stmmac_ethtool_ops = {. Begin = stmmac_check_if_running,. Get_drvinfo = Stmmac_ethtool_g Etdrvinfo,. get_settings = Stmmac_ethtool_getsettings,. set_settings = Stmmac_ethtool_setsettings,. Get_msglev
    El = 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_pausep Aram,. Set_pauseparam = Stmmac_set_pauseparam,. get_ethtool_stats = Stmmac_get_ethtool_stats,. get_strings = S Tmmac_get_strings,. Get_wol = Stmmac_get_wol,. Set_wol = Stmmac_set_wol,. Get_sset_count = Stmmac_get_sset_cou

NT,}; 6. Set Watchdog_timeo time in the first 5 steps, can also initialize Mac_device_info, and realize its Mdio_bus bus degree yoke 7.register_netdev (ndev) register to the kernel.

Generates ETH0/1/2 nodes. 8. Initialize the Mdiobus read-write function and register the Bus->dev, then detect the PHY on the Mii bus.
 After discovering a valid PHY, perform 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 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!=);
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
    NUL L;

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); C2/>PRINTK (kern_info "ID1 = 0x%x at%s \ n", phy_reg,bus->name);
if (Phy_reg < 0)
    Return-eio;

*phy_id = (Phy_reg & 0xffff) <<;

/* 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. Initialize Sk_buff queue header, Skb_queue_head_init. Then the application is interrupted and the interrupt is turned on.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.