master/ethernet.c
changeset 2625 e25af8bd3957
parent 2593 e2388daebfbc
child 2626 713058b68b43
equal deleted inserted replaced
2624:ecef88726fc3 2625:e25af8bd3957
    77 // net_device functions
    77 // net_device functions
    78 int ec_eoedev_open(struct net_device *);
    78 int ec_eoedev_open(struct net_device *);
    79 int ec_eoedev_stop(struct net_device *);
    79 int ec_eoedev_stop(struct net_device *);
    80 int ec_eoedev_tx(struct sk_buff *, struct net_device *);
    80 int ec_eoedev_tx(struct sk_buff *, struct net_device *);
    81 struct net_device_stats *ec_eoedev_stats(struct net_device *);
    81 struct net_device_stats *ec_eoedev_stats(struct net_device *);
       
    82 static int ec_eoedev_set_mac(struct net_device *netdev, void *p);
    82 
    83 
    83 /*****************************************************************************/
    84 /*****************************************************************************/
    84 
    85 
    85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
    86 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
    86 /** Device operations for EoE interfaces.
    87 /** Device operations for EoE interfaces.
    88 static const struct net_device_ops ec_eoedev_ops = {
    89 static const struct net_device_ops ec_eoedev_ops = {
    89     .ndo_open = ec_eoedev_open,
    90     .ndo_open = ec_eoedev_open,
    90     .ndo_stop = ec_eoedev_stop,
    91     .ndo_stop = ec_eoedev_stop,
    91     .ndo_start_xmit = ec_eoedev_tx,
    92     .ndo_start_xmit = ec_eoedev_tx,
    92     .ndo_get_stats = ec_eoedev_stats,
    93     .ndo_get_stats = ec_eoedev_stats,
       
    94     .ndo_set_mac_address = ec_eoedev_set_mac,
    93 };
    95 };
    94 #endif
    96 #endif
       
    97 
       
    98 /*****************************************************************************/
       
    99 
       
   100 /**
       
   101  * ec_eoedev_set_mac - Change the Ethernet Address of the NIC
       
   102  * @netdev: network interface device structure
       
   103  * @p: pointer to an address structure
       
   104  *
       
   105  * Returns 0 on success, negative on failure
       
   106  **/
       
   107 static int
       
   108 ec_eoedev_set_mac(struct net_device *netdev, void *p)
       
   109 {
       
   110    struct sockaddr *addr = p;
       
   111 
       
   112    if (!is_valid_ether_addr(addr->sa_data))
       
   113       return -EADDRNOTAVAIL;
       
   114 
       
   115    memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
       
   116 
       
   117    return 0;
       
   118 }
    95 
   119 
    96 /*****************************************************************************/
   120 /*****************************************************************************/
    97 
   121 
    98 /** EoE constructor.
   122 /** EoE constructor.
    99  *
   123  *
   105         ec_eoe_t *eoe, /**< EoE handler */
   129         ec_eoe_t *eoe, /**< EoE handler */
   106         ec_slave_t *slave /**< EtherCAT slave */
   130         ec_slave_t *slave /**< EtherCAT slave */
   107         )
   131         )
   108 {
   132 {
   109     ec_eoe_t **priv;
   133     ec_eoe_t **priv;
   110     int i, ret = 0;
   134     int ret = 0;
   111     char name[EC_DATAGRAM_NAME_SIZE];
   135     char name[EC_DATAGRAM_NAME_SIZE];
       
   136 
       
   137     struct net_device *dev;
       
   138     unsigned char lo_mac[ETH_ALEN] = {0};
       
   139     unsigned int use_master_mac = 0;
   112 
   140 
   113     eoe->slave = slave;
   141     eoe->slave = slave;
   114 
   142 
   115     ec_datagram_init(&eoe->datagram);
   143     ec_datagram_init(&eoe->datagram);
   116     eoe->queue_datagram = 0;
   144     eoe->queue_datagram = 0;
   163     eoe->dev->stop = ec_eoedev_stop;
   191     eoe->dev->stop = ec_eoedev_stop;
   164     eoe->dev->hard_start_xmit = ec_eoedev_tx;
   192     eoe->dev->hard_start_xmit = ec_eoedev_tx;
   165     eoe->dev->get_stats = ec_eoedev_stats;
   193     eoe->dev->get_stats = ec_eoedev_stats;
   166 #endif
   194 #endif
   167 
   195 
   168     for (i = 0; i < ETH_ALEN; i++)
   196     // First check if the MAC address assigned to the master is globally unique
   169         eoe->dev->dev_addr[i] = i | (i << 4);
   197     if ((slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[0] & 0x02) != 0x02) {
       
   198         // The master MAC is unique and the NIC part can be used for the EoE interface MAC
       
   199         use_master_mac = 1;
       
   200     }
       
   201     else {
       
   202         // The master MAC is not unique, so we check for unique MAC in other interfaces
       
   203         dev = first_net_device(&init_net);
       
   204         while (dev) {
       
   205             // Check if globally unique MAC address
       
   206             if (dev->addr_len == ETH_ALEN) {
       
   207                 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) {
       
   208                     if ((dev->dev_addr[0] & 0x02) != 0x02) {
       
   209                         // The first globally unique MAC address has been identified
       
   210                         break;
       
   211                     }
       
   212                 }
       
   213             }
       
   214             dev = next_net_device(dev);
       
   215         }
       
   216         if (eoe->dev->addr_len == ETH_ALEN) {
       
   217             if (dev) {
       
   218                 // A unique MAC were identified in one of the other network interfaces
       
   219                 // and the NIC part can be used for the EoE interface MAC.
       
   220                 EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address",
       
   221                     eoe->dev->name, dev->name);
       
   222                 eoe->dev->dev_addr[1] = dev->dev_addr[3];
       
   223                 eoe->dev->dev_addr[2] = dev->dev_addr[4];
       
   224                 eoe->dev->dev_addr[3] = dev->dev_addr[5];
       
   225             }
       
   226             else {
       
   227                 use_master_mac = 1;
       
   228             }
       
   229         }
       
   230     }
       
   231     if (eoe->dev->addr_len == ETH_ALEN) {
       
   232         if (use_master_mac) {
       
   233             EC_SLAVE_INFO(slave, "%s MAC address derived from NIC part of %s MAC address",
       
   234                 eoe->dev->name, slave->master->devices[EC_DEVICE_MAIN].dev->name);
       
   235             eoe->dev->dev_addr[1] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[3];
       
   236             eoe->dev->dev_addr[2] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[4];
       
   237             eoe->dev->dev_addr[3] = slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[5];
       
   238         }
       
   239         eoe->dev->dev_addr[0] = 0x02;
       
   240         eoe->dev->dev_addr[4] = (uint8_t)(slave->ring_position >> 8);
       
   241         eoe->dev->dev_addr[5] = (uint8_t)(slave->ring_position);
       
   242     }
   170 
   243 
   171     // initialize private data
   244     // initialize private data
   172     priv = netdev_priv(eoe->dev);
   245     priv = netdev_priv(eoe->dev);
   173     *priv = eoe;
   246     *priv = eoe;
   174 
   247 
   186         EC_SLAVE_ERR(slave, "Unable to register net_device:"
   259         EC_SLAVE_ERR(slave, "Unable to register net_device:"
   187                 " error %i\n", ret);
   260                 " error %i\n", ret);
   188         goto out_free;
   261         goto out_free;
   189     }
   262     }
   190 
   263 
   191     // make the last address octet unique
       
   192     eoe->dev->dev_addr[ETH_ALEN - 1] = (uint8_t) eoe->dev->ifindex;
       
   193     return 0;
   264     return 0;
   194 
   265 
   195  out_free:
   266  out_free:
   196     free_netdev(eoe->dev);
   267     free_netdev(eoe->dev);
   197     eoe->dev = NULL;
   268     eoe->dev = NULL;