master/ethernet.c
changeset 2635 42b62867574d
parent 2626 713058b68b43
child 2641 535465bf176d
equal deleted inserted replaced
2634:f859d567f94e 2635:42b62867574d
    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
   169         eoe->dev->dev_addr[i] = i | (i << 4);
   197     // unique
       
   198     if ((slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[0] & 0x02) !=
       
   199             0x02) {
       
   200         // The master MAC is unique and the NIC part can be used for the EoE
       
   201         // interface MAC
       
   202         use_master_mac = 1;
       
   203     }
       
   204     else {
       
   205         // The master MAC is not unique, so we check for unique MAC in other
       
   206         // interfaces
       
   207         dev = first_net_device(&init_net);
       
   208         while (dev) {
       
   209             // Check if globally unique MAC address
       
   210             if (dev->addr_len == ETH_ALEN) {
       
   211                 if (memcmp(dev->dev_addr, lo_mac, ETH_ALEN) != 0) {
       
   212                     if ((dev->dev_addr[0] & 0x02) != 0x02) {
       
   213                         // The first globally unique MAC address has been
       
   214                         // identified
       
   215                         break;
       
   216                     }
       
   217                 }
       
   218             }
       
   219             dev = next_net_device(dev);
       
   220         }
       
   221         if (eoe->dev->addr_len == ETH_ALEN) {
       
   222             if (dev) {
       
   223                 // A unique MAC were identified in one of the other network
       
   224                 // interfaces and the NIC part can be used for the EoE
       
   225                 // interface MAC.
       
   226                 EC_SLAVE_INFO(slave, "%s MAC address derived from"
       
   227                         " NIC part of %s MAC address",
       
   228                     eoe->dev->name, dev->name);
       
   229                 eoe->dev->dev_addr[1] = dev->dev_addr[3];
       
   230                 eoe->dev->dev_addr[2] = dev->dev_addr[4];
       
   231                 eoe->dev->dev_addr[3] = dev->dev_addr[5];
       
   232             }
       
   233             else {
       
   234                 use_master_mac = 1;
       
   235             }
       
   236         }
       
   237     }
       
   238     if (eoe->dev->addr_len == ETH_ALEN) {
       
   239         if (use_master_mac) {
       
   240             EC_SLAVE_INFO(slave, "%s MAC address derived"
       
   241                     " from NIC part of %s MAC address",
       
   242                 eoe->dev->name,
       
   243                 slave->master->devices[EC_DEVICE_MAIN].dev->name);
       
   244             eoe->dev->dev_addr[1] =
       
   245                 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[3];
       
   246             eoe->dev->dev_addr[2] =
       
   247                 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[4];
       
   248             eoe->dev->dev_addr[3] =
       
   249                 slave->master->devices[EC_DEVICE_MAIN].dev->dev_addr[5];
       
   250         }
       
   251         eoe->dev->dev_addr[0] = 0x02;
       
   252         eoe->dev->dev_addr[4] = (uint8_t)(slave->ring_position >> 8);
       
   253         eoe->dev->dev_addr[5] = (uint8_t)(slave->ring_position);
       
   254     }
   170 
   255 
   171     // initialize private data
   256     // initialize private data
   172     priv = netdev_priv(eoe->dev);
   257     priv = netdev_priv(eoe->dev);
   173     *priv = eoe;
   258     *priv = eoe;
   174 
   259 
   186         EC_SLAVE_ERR(slave, "Unable to register net_device:"
   271         EC_SLAVE_ERR(slave, "Unable to register net_device:"
   187                 " error %i\n", ret);
   272                 " error %i\n", ret);
   188         goto out_free;
   273         goto out_free;
   189     }
   274     }
   190 
   275 
   191     // make the last address octet unique
       
   192     eoe->dev->dev_addr[ETH_ALEN - 1] = (uint8_t) eoe->dev->ifindex;
       
   193     return 0;
   276     return 0;
   194 
   277 
   195  out_free:
   278  out_free:
   196     free_netdev(eoe->dev);
   279     free_netdev(eoe->dev);
   197     eoe->dev = NULL;
   280     eoe->dev = NULL;
   264 
   347 
   265     if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) {
   348     if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) {
   266         current_size = remaining_size;
   349         current_size = remaining_size;
   267         last_fragment = 1;
   350         last_fragment = 1;
   268     } else {
   351     } else {
   269         current_size = ((eoe->slave->configured_tx_mailbox_size - 10) / 32) * 32;
   352         current_size =
       
   353             ((eoe->slave->configured_tx_mailbox_size - 10) / 32) * 32;
   270         last_fragment = 0;
   354         last_fragment = 0;
   271     }
   355     }
   272 
   356 
   273     if (eoe->tx_fragment_number) {
   357     if (eoe->tx_fragment_number) {
   274         complete_offset = eoe->tx_offset / 32;
   358         complete_offset = eoe->tx_offset / 32;