Linux网络设备的系统调用

来源:互联网 发布:数据魔方多少钱 编辑:程序博客网 时间:2024/05/22 02:01
转自: http://www.tuicool.com/articles/QJfmUr在用户层上的程序, 建立本地socket后,使用ioctl读取phy芯片的寄存器。ioctl(sockfd, SIOCGMIIREG, &ifr);下面是linux的网络设备驱动程序响应用户层的ioctl命令过程间各个阶段的函数调用。ioclt 系统调用层:fs/ioctl.cSYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg){ ...error = do_vfs_ioctl(filp, fd, cmd, arg);...}int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,                                                                    unsigned long arg){switch (cmd) {...default:       ...            error = vfs_ioctl(filp, cmd, arg);...}static long vfs_ioctl(struct file *filp, unsigned int cmd,unsigned long arg){ ...*如果文件操作方法--无锁的的ioctl有对应实现函数(函数指针unlock_ioctl有被填充), 则调用unlcok_ioctl的实现函数*/if (filp->f_op->unlocked_ioctl) {        error = filp->f_op->unlocked_ioctl(filp, cmd, arg);...}unlock_ioctl 的实现层:net/socket.cstatic const struct file_operations socket_file_ops = {...    .unlocked_ioctl = sock_ioctl,...}static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg){   ...switch (cmd) {... default:            err = sock->ops->ioctl(sock, cmd, arg);            if (err == -ENOIOCTLCMD)                err = dev_ioctl(net, cmd, argp);...}net/core/dev.c//dev_ioctl :  network device ioctldev_ioctl(){switch (cmd) {...    case SIOCGMIIPHY:    case SIOCGMIIREG:    case SIOCSIFNAME:        ret = dev_ifsioc(net, &ifr, cmd);static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)                                                             {switch (cmd) {...    default:            if (ops->ndo_do_ioctl) {                if (netif_device_present(dev))                    err = ops->ndo_do_ioctl(dev, ifr, cmd);...}ndo_do_ioctl 的实现层:drivers/net/octeon/octeon_mgmt.cstatic int __init octeon_mgmt_mod_init(void){    /* Force our mdiobus driver module to be loaded first. */    octeon_mdiobus_force_mod_depencency();    return platform_driver_register(&octeon_mgmt_driver);} static struct platform_driver octeon_mgmt_driver = {    .driver = {        .name       = "octeon_mgmt",        .owner      = THIS_MODULE,        .of_match_table = octeon_mgmt_match,    },      .probe      = octeon_mgmt_probe,    .remove     = __exit_p(octeon_mgmt_remove),}; static struct of_device_id octeon_mgmt_match[] = {    {        .compatible = "cavium,octeon-5750-mix",    },      {},  };  MODULE_DEVICE_TABLE(of, octeon_mgmt_match);static int __init octeon_mgmt_probe(struct platform_device *pdev){   ...      netdev->netdev_ops = &octeon_mgmt_ops;    netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; ...   static const struct net_device_ops octeon_mgmt_ops = {                                                                                             .ndo_open =         octeon_mgmt_open,    .ndo_stop =         octeon_mgmt_stop,    .ndo_start_xmit =       octeon_mgmt_xmit,    .ndo_set_rx_mode =      octeon_mgmt_set_rx_filtering,    .ndo_set_multicast_list =   octeon_mgmt_set_rx_filtering,    .ndo_set_mac_address =      octeon_mgmt_set_mac_address,    .ndo_do_ioctl =         octeon_mgmt_ioctl,    .ndo_change_mtu =       octeon_mgmt_change_mtu,#ifdef CONFIG_NET_POLL_CONTROLLER    .ndo_poll_controller =      octeon_mgmt_poll_controller,#endif};    static int octeon_mgmt_ioctl(struct net_device *netdev,                                                                                                         struct ifreq *rq, int cmd){      default:        if (p->phydev)            return phy_mii_ioctl(p->phydev, if_mii(rq), cmd);        return -EINVAL;    }}  drivers/net/phy/phy.cint phy_mii_ioctl(struct phy_device *phydev,        struct mii_ioctl_data *mii_data, int cmd){      switch (cmd) {    case SIOCGMIIPHY:        mii_data->phy_id = phydev->addr;        case SIOCGMIIREG:        mii_data->val_out = phy_read(phydev, mii_data->reg_num);        break;    ...}include/linux/phy.hstatic inline int phy_read(struct phy_device *phydev, u32 regnum)                                                                              {    return mdiobus_read(phydev->bus, phydev->addr, regnum);}  drivers/net/phy/mdio_bus.cint mdiobus_read(struct mii_bus *bus, int addr, u32 regnum){    retval = bus->read(bus, addr, regnum);...}bus->read 的实现层drivers/net/phy/mdio-octeon.cstatic int __init octeon_mdiobus_mod_init(void){      return platform_driver_register(&octeon_mdiobus_driver);}       static struct platform_driver octeon_mdiobus_driver = {    .driver = {        .name       = "mdio-octeon",        .owner      = THIS_MODULE,        .of_match_table = octeon_mdiobus_match,    },    .probe      = octeon_mdiobus_probe,    .remove     = __exit_p(octeon_mdiobus_remove),};    static struct of_device_id octeon_mdiobus_match[] = {    {        .compatible = "cavium,octeon-3860-mdio",    },    {},};  MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);static int __init octeon_mdiobus_probe(struct platform_device *pdev){  ...        bus->mii_bus->read = octeon_mdiobus_read;    bus->mii_bus->write = octeon_mdiobus_write; ...}octeon_mdiobus_read 是最底层的实现函数。
0 0
原创粉丝点击